日期:2025.9.3

需求:
1.一键连新增注销账号功能
2.删除OpenInstall定量采集功能(openInstall只有一个账号和一个渠道使用)
This commit is contained in:
level 2025-09-03 09:36:07 +08:00
parent e3f8934195
commit 364d4beb61
18 changed files with 354 additions and 59 deletions

View File

@ -15,7 +15,7 @@ dependencies {
implementation(fileTree(mapOf("dir" to "src/main/libs", "include" to listOf("*.aar"))))
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
implementation(files("src\\main\\libs\\Baidu_ocpc_action_2_7_2.aar"))
implementation(files("src\\main\\libs\\OpenInstall.jar"))
// implementation(files("src\\main\\libs\\OpenInstall.jar"))
// implementation("com.google.firebase:firebase-crashlytics-buildtools:3.0.2")
// implementation(files("src/main/libs/openinstall.jar"))

View File

@ -45,13 +45,13 @@
android:name="releaseCode"
android:value="@integer/release_code" />
<meta-data
android:name="com.openinstall.APP_KEY"
android:value="ltbqy7"/>
<!-- 使用广告推广-->
<meta-data
android:name="com.openinstall.AD_TRACK"
android:value="true"/>
<!-- <meta-data-->
<!-- android:name="com.openinstall.APP_KEY"-->
<!-- android:value="ltbqy7"/>-->
<!--&lt;!&ndash; 使用广告推广&ndash;&gt;-->
<!-- <meta-data-->
<!-- android:name="com.openinstall.AD_TRACK"-->
<!-- android:value="true"/>-->
<activity
android:name=".act.SplashActivity"

View File

@ -40,19 +40,25 @@ import com.yingmao.clash.base.BaseActivity
import com.yingmao.clash.conf.BZYConstants
import com.yingmao.clash.conf.Conf
import com.yingmao.clash.entity.LanguageInfoEntity
import com.yingmao.clash.fragment.NewAccFragment
import com.yingmao.clash.fragment.NewAccFragment.Companion.clashRunning
import com.yingmao.clash.net.http.HttpReqType
import com.yingmao.clash.net.http.HttpStatus
import com.yingmao.clash.net.http.entity.AppVersionCheckRsp
import com.yingmao.clash.net.http.entity.ParamData
import com.yingmao.clash.net.http.entity.UploadParamData
import com.yingmao.clash.util.CommonUtils
import com.yingmao.clash.util.DataUtils
import com.yingmao.clash.util.DataUtils.getAllFilePath
import com.yingmao.clash.util.stopClashService
import com.yingmao.clash.view.RxToast
import com.yingmao.clash.view.adapter.LanguageAdapter
import com.yingmao.clash.view.dialog.DialogDoMainChoose
import com.yingmao.clash.view.dialog.DialogSureCancelLogOut
import com.yingmao.clash.view.popwindow.CommonPopupWindow
import com.yingmao.clash.vm.MainAtyVM
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.delay
@ -75,6 +81,7 @@ class SettingActivity : BaseActivity() {
private lateinit var clApplicationModeTitleStr: ConstraintLayout
private lateinit var llControlApplication: ConstraintLayout
private lateinit var clSwitching:ConstraintLayout
private lateinit var clDelete: ConstraintLayout
private lateinit var tVApplicationModeTxt:TextView
private var popupWindow: CommonPopupWindow? = null
private var layoutGravity: CommonPopupWindow.LayoutGravity? = null
@ -99,6 +106,23 @@ class SettingActivity : BaseActivity() {
llControlApplication=findViewById(R.id.llControlApplication)
tVApplicationModeTxt=findViewById(R.id.TVApplicationModeTxt)
clSwitching=findViewById(R.id.clSwitching)
clDelete=findViewById(R.id.clDelete)
clDelete.setOnClickListener {
val splashDialog =
DialogSureCancelLogOut(this)
splashDialog.showDialog(this@SettingActivity)
splashDialog.setOnDialogClickListener(object : DialogSureCancelLogOut.ActivityLinkListener{
override fun onAgreeClickListener() {
mainAtyVM.getLogoutDel()
splashDialog.cancel()
}
override fun onDisagreeClickListener() {
splashDialog.cancel()
}
})
}
clSwitching.setOnClickListener {
android.util.Log.i("SourceSwitching","clashRunning::"+ clashRunning)
@ -549,6 +573,15 @@ class SettingActivity : BaseActivity() {
}else{
hideLoading()
}
}else if(httpStatus.reqType == HttpReqType.LogOutDel){
val logOutDel = httpStatus.rsp as AppVersionCheckRsp
if(logOutDel.code==200){
Log.d("back data::${httpStatus.rsp}")
//跳转到登录页面
cleanUserInfo()
finish()
}
}
}
private fun finishInit() {
@ -699,4 +732,34 @@ class SettingActivity : BaseActivity() {
}
}
private fun cleanUserInfo() {
MMKV.defaultMMKV().removeValueForKey(BZYConstants.MMKV_KEY_PH_TOKEN)
MMKV.defaultMMKV().removeValueForKey(BZYConstants.MMKV_KEY_TOKEN)
MMKV.defaultMMKV().removeValueForKey(BZYConstants.MMKV_KEY_CURRENT_NODE)
MMKV.defaultMMKV().removeValueForKey(BZYConstants.NODE_SELECTED_NAME_KEY)
MMKV.defaultMMKV().removeValueForKey(BZYConstants.MMKV_KEY_VPN_UserCommand)
MMKV.defaultMMKV().removeValueForKey(BZYConstants.NODE_All_ITEM_NAME_KEY)
MMKV.defaultMMKV().removeValueForKey(BZYConstants.PROFILE_SUB_URL)
Log.d("cleanUserInfo clashRunning==>${clashRunning}")
if (clashRunning) {
stopClashService()
}
mainAtyVM.stopHeartBeat()
cleanProfile()
startActivity(Intent(CommonUtils.getApp(), LoginActivity::class.java))
finish()
}
private fun cleanProfile() {
Log.d("cleanProfile start")
GlobalScope.launch(Dispatchers.IO) {
profileBinder?.let { pm ->
pm.queryAll().forEach { profile ->
Log.d("cleanProfile go delete name==>${profile.name}, uuid==>${profile.uuid}")
pm.delete(profile.uuid)
}
} ?: let {
Log.d("profileBinder is null")
}
}
}
}

View File

@ -2,7 +2,6 @@ package com.yingmao.clash.act
import android.annotation.SuppressLint
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import android.os.Bundle
@ -18,7 +17,6 @@ import android.widget.Button
import android.widget.ProgressBar
import android.widget.RelativeLayout
import android.widget.TextView
import androidx.core.content.ContextCompat
import androidx.core.content.FileProvider
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
@ -28,10 +26,6 @@ import com.baidu.mobads.action.PrivacyStatus
import com.cncat.vpn.service.ClashManager
import com.cncat.vpn.service.remote.IClashManager
import com.cncat.vpn.service.remote.wrap
import com.fm.openinstall.Configuration
import com.fm.openinstall.OpenInstall
import com.fm.openinstall.listener.AppWakeUpAdapter
import com.fm.openinstall.model.AppData
import com.github.gzuliyujiang.oaid.DeviceID
import com.github.gzuliyujiang.oaid.DeviceIdentifier
import com.google.gson.JsonObject
@ -67,6 +61,7 @@ import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.io.File
import java.util.Locale
@SuppressLint("CustomSplashScreen")
class SplashActivity : BaseActivity() {
private lateinit var rlPb: View
@ -194,24 +189,24 @@ class SplashActivity : BaseActivity() {
// android.util.Log.i("AAAAAAAAAAA","data:::"+byteArrayToHexStr)
// 获取拉起参数
openinstall()
}
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
// 此处要调用否则App在后台运行时会无法获取
OpenInstall.getWakeUp(intent, wakeUpAdapter)
}
private var wakeUpAdapter: AppWakeUpAdapter = object : AppWakeUpAdapter() {
override fun onWakeUp(appData: AppData) {
// 打印数据便于调试
Log.d("OpenInstall", "getWakeUp : wakeupData = $appData")
// 获取渠道编号参数
val channelCode = appData.getChannel()
// 获取自定义参数
val bindData = appData.getData()
Log.d("OpenInstall", "channelCode : bindData = $channelCode"+"bindData::"+bindData)
}
// openinstall()
}
// override fun onNewIntent(intent: Intent?) {
// super.onNewIntent(intent)
// // 此处要调用否则App在后台运行时会无法获取
// OpenInstall.getWakeUp(intent, wakeUpAdapter)
// }
// private var wakeUpAdapter: AppWakeUpAdapter = object : AppWakeUpAdapter() {
// override fun onWakeUp(appData: AppData) {
// // 打印数据便于调试
// Log.d("OpenInstall", "getWakeUp : wakeupData = $appData")
// // 获取渠道编号参数
// val channelCode = appData.getChannel()
// // 获取自定义参数
// val bindData = appData.getData()
// Log.d("OpenInstall", "channelCode : bindData = $channelCode"+"bindData::"+bindData)
// }
// }
@SuppressLint("JavascriptInterface", "SetJavaScriptEnabled")
private fun setWebView() {
rlPb.visibility = View.INVISIBLE
@ -708,24 +703,12 @@ class SplashActivity : BaseActivity() {
}
startActivity(intent)
}
private fun openinstall() {
// 所有的设备标识符开发者都可控制,请参考集成文档
val configuration: Configuration? = Configuration.Builder() //
// .serialNumber(null) // 禁止 SDK 获取 serialNumber
// 只有在使用“移动广告效果监测”功能时才开启
// .adEnabled(true)
// .imeiDisabled() // 禁止 SDK 获取 imei
// .oaid("传入获取到的oaid")
.build()
OpenInstall.init(this, configuration)
//获取唤醒参数
OpenInstall.getWakeUp(intent, wakeUpAdapter)
// 1、如果在“Android集成” -> “Android下载配置” 中启用了 “集成应用宝” 开关并填入正确的应用宝地址
// 请替换使用 getWakeUpYYB ,则可实现微信/QQ中打开应用并还原参数
// OpenInstall.getWakeUpYYB(SplashActivity.this, getIntent(), wakeUpAdapter);
// 2、 如果想只要调用了接口,无论是否有数据时都走回调
// 请替换使用 getWakeUpAlwaysCallback ,则可统一在回调中做业务跳转
// OpenInstall.getWakeUpAlwaysCallback(getIntent(), wakeUpAdapter);
}
// private fun openinstall() {
// // 所有的设备标识符开发者都可控制,请参考集成文档
// val configuration: Configuration? = Configuration.Builder()
// .build()
//
// OpenInstall.init(this, configuration)
// OpenInstall.getWakeUp(intent, wakeUpAdapter)
// }
}

View File

@ -13,7 +13,6 @@ import com.baidu.mobads.action.BaiduAction
import com.cncat.vpn.common.Global
import com.cncat.vpn.common.compat.currentProcessName
import com.cncat.vpn.common.log.Log
import com.fm.openinstall.OpenInstall
import com.github.gzuliyujiang.oaid.DeviceID
import com.github.gzuliyujiang.oaid.DeviceIdentifier
import com.github.gzuliyujiang.oaid.IGetter
@ -112,7 +111,7 @@ class MainApplication : Application() {
mainApplication,
"pk_live_51Nkl6vLWP3xWXY4LfXtdMtXzHazv6pav2rH1p1BfICeh5meGGjglExiw4GgmSzWO7NptEM1c549Fe11zRy9nCfxs009zEwLpXP"
)
OpenInstall.preInit(mainApplication)
// OpenInstall.preInit(mainApplication)
}
}

View File

@ -132,12 +132,12 @@ interface HttpApi {
suspend fun getHostGithubjl(): String
//客服链接
@GET("/oss/kf/yjl_kefu.txt")
@GET("/oss/kf/gz_kefu.txt")
suspend fun getLocalKefuHost(): String
@GET("kf/yjl_kefu.txt")
@GET("kf/gz_kefu.txt")
suspend fun getKklNetHost(): String
@GET("/yjl_kefu.txt")
@GET("/gz_kefu.txt")
suspend fun getKklNetS3(): String
@Headers(
"User-Agent: Octopus_Android"
@ -368,4 +368,8 @@ interface HttpApi {
BZYConstants.MMKV_KEY_TOKEN
).toString(),
): Response<NormalRsp>
@GET("/netbarcloud/vpn/logoutDel")
suspend fun logOutDel(
@QueryMap params: Map<String, String>,
): AppVersionCheckRsp
}

View File

@ -32,5 +32,6 @@ enum class HttpReqType(type: Int) {
StripeWeChat(53),
SelectNode(54),
BaseREGISTER(55),
Report(56)
Report(56),
LogOutDel(57)
}

View File

@ -0,0 +1,78 @@
package com.yingmao.clash.view.dialog;
import android.annotation.SuppressLint;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.view.Gravity;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.CheckBox;
import android.widget.TextView;
import com.yingmao.clash.R;
import com.yingmao.clash.act.AgreementAndPrivacyActivity;
import com.yingmao.clash.conf.BZYConstants;
import com.yingmao.clash.view.RxToast;
public class DialogSureCancelLogOut extends Dialog {
public DialogSureCancelLogOut(Context context) {
super(context);
setContentView(R.layout.dialog_log_out_false);
//设置点击布局外则Dialog消失
setCanceledOnTouchOutside(false);
}
@SuppressLint("SetTextI18n")
public void showDialog(Context context) {
Window window = getWindow();
//设置弹窗动画
assert window != null;
window.setWindowAnimations(R.style.style_dialog);
//设置Dialog背景色
window.setBackgroundDrawableResource(R.color.colorTransparent);
WindowManager.LayoutParams wl = window.getAttributes();
//设置弹窗位置
wl.gravity = Gravity.CENTER;
window.setAttributes(wl);
show();
CheckBox cbXhe=findViewById(R.id.cbXhe);
TextView noAgree=findViewById(R.id.tv_cancel);
TextView agree=findViewById(R.id.tv_sure);
noAgree.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(activityLinkListener!=null){
activityLinkListener.onDisagreeClickListener();
}
}
});
agree.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(activityLinkListener!=null){
if(cbXhe.isChecked()){
activityLinkListener.onAgreeClickListener();
}else {
RxToast.info(context.getString(R.string.checkStr));
}
}
}
});
}
/********************** 回调 ************************/
private ActivityLinkListener activityLinkListener;
public void setOnDialogClickListener(ActivityLinkListener activityLinkListener){
this.activityLinkListener = activityLinkListener;
}
public interface ActivityLinkListener{
void onAgreeClickListener();
void onDisagreeClickListener();
}
}

View File

@ -218,4 +218,14 @@ class MainAtyVM : PublicViewMode() {
jsonString.toRequestBody("application/json; charset=utf-8".toMediaType())
doAsync(HttpReqType.Report) { httpApi.getReport(paramsToken, requestBody) }
}
fun getLogoutDel(){
val httpApi = NetService.instances.createHttps(HttpApi::class.java)
val username = MMKV.defaultMMKV().decodeString(BZYConstants.MMKV_KEY_REMEMBER_USERNAME,"")!!
val phToken = MMKV.defaultMMKV().decodeString(BZYConstants.MMKV_KEY_PH_TOKEN,"")!!
val params = hashMapOf(
"phoneNumber" to username,
"phToken" to phToken,
)
doAsync(HttpReqType.LogOutDel){httpApi.logOutDel(params)}
}
}

Binary file not shown.

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#BFD5D5D5" >
<item>
<shape>
<gradient android:type="linear"
android:angle="180"
android:startColor="#FFF"
android:endColor="#FFF"
/>
<corners android:radius="20dp"/>
</shape>
</item>
</ripple>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<stroke android:width="1dp" android:color="@color/black"/>
<corners android:radius="24dp"/>
</shape>
</item>
</selector>

View File

@ -209,8 +209,6 @@
android:layout_marginStart="21dp"
android:layout_marginEnd="21dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
app:layout_constraintBottom_toBottomOf="parent"
>
<TextView
@ -236,6 +234,43 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/tvChushihua" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/clDelete"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/clChushihua"
android:layout_marginStart="21dp"
android:layout_marginEnd="21dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
app:layout_constraintBottom_toBottomOf="parent"
>
<TextView
android:id="@+id/tvDelete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:text="@string/deleteStr"
android:textColor="#5A2B31"
android:textSize="16sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/aiDelete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/oc_xy"
app:layout_constraintBottom_toBottomOf="@+id/tvDelete"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/tvDelete" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout

View File

@ -0,0 +1,86 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/logout_linea_bg"
android:gravity="center"
android:orientation="vertical"
android:paddingBottom="28dp"
>
<ImageView
android:id="@+id/iv_logo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="12dp"
android:visibility="gone"
/>
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="20dp"
android:visibility="gone"
/>
<TextView
android:id="@+id/tv_content"
android:layout_width="240dp"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginTop="40dp"
android:layout_marginBottom="34dp"
android:layout_marginRight="20dp"
android:gravity="center"
android:paddingLeft="3dp"
android:paddingRight="3dp"
android:text="@string/DeleteStr"
android:textColor="@color/black"
android:textSize="18sp"
android:textStyle="bold"
/>
<CheckBox
android:id="@+id/cbXhe"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/logOutStr"
android:layout_marginStart="20dp"
android:layout_marginEnd="20dp"
android:textColor="@color/red"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="10dp"
android:gravity="center"
android:orientation="horizontal">
<TextView
android:id="@+id/tv_cancel"
android:layout_width="wrap_content"
android:layout_height="46dp"
android:gravity="center"
android:text="@string/cancel"
android:layout_weight="1"
android:layout_marginStart="10dp"
android:background="@drawable/logout_selector"
android:textColor="@color/black"
android:layout_marginEnd="20dp"
android:textSize="16sp" />
<TextView
android:id="@+id/tv_sure"
android:layout_width="wrap_content"
android:layout_height="46dp"
android:gravity="center"
android:text="@string/delete"
android:layout_weight="1"
android:layout_marginEnd="@dimen/dp_10"
android:background="@drawable/logout_selector"
android:textColor="@color/black"
android:textSize="16sp" />
</LinearLayout>
</LinearLayout>

View File

@ -409,4 +409,7 @@ In order to implement and strengthen awareness of personal information security
<string name="PayError">PayError:</string>
<string name="payDelayStr">\u3000\u3000Your payment order has been successfully completed and is currently being processed by the platform. There is typically a delay of several seconds before your funds arrive, so please wait. If you returned to the app homepage, we recommend waiting a moment and then manually refreshing the page to update the status. If your funds still have not arrived after a few minutes, please contact customer service. Thank you for your support and trust</string>
<string name="AlreadyKnown">Already Known</string>
<string name="DeleteStr">Delete account</string>
<string name="logOutStr"> Please note! You will not be able to log in using this account after deleting it</string>
<string name="checkStr">Please check the box to indicate that you agree to delete the account</string>
</resources>

View File

@ -400,4 +400,7 @@
<string name="PayError">支付失敗:</string>
<string name="payDelayStr">\u3000\u3000您的支付訂單已成功完成目前平台正在處理中。通常情況下到帳會有幾秒鐘的延遲請您稍作等待。如您已返回應用程式首頁建議等待片刻後手動刷新頁面以便更新狀態。若幾分鐘後仍未到賬請及時聯絡客服人員為您處理。感謝您的支持與信任</string>
<string name="AlreadyKnown">已知晓</string>
<string name="DeleteStr">刪除賬號</string>
<string name="logOutStr"> 請註意! 刪除賬號之後將不能在使用該賬號進行登錄</string>
<string name="checkStr">請勾選復選框表明你同意刪除賬號</string>
</resources>

View File

@ -398,4 +398,7 @@
<string name="PayError">支付失敗:</string>
<string name="payDelayStr">\u3000\u3000您的支付訂單已成功完成目前平台正在處理中。通常情況下到帳會有幾秒鐘的延遲請您稍作等待。如您已返回應用程式首頁建議等待片刻後手動刷新頁面以便更新狀態。若幾分鐘後仍未到賬請及時聯絡客服人員為您處理。感謝您的支持與信任</string>
<string name="AlreadyKnown">已知晓</string>
<string name="DeleteStr">刪除賬號</string>
<string name="logOutStr"> 請註意! 刪除賬號之後將不能在使用該賬號進行登錄</string>
<string name="checkStr">請勾選復選框表明你同意刪除賬號</string>
</resources>

View File

@ -426,4 +426,7 @@
<string name="PayError">支付失败:</string>
<string name="payDelayStr">\u3000\u3000您的支付订单已成功完成目前平台正在处理中。通常情况下到账会有几秒钟的延迟请您稍作等待。如您已返回应用首页建议等待片刻后手动刷新页面以便更新状态。若几分钟后仍未到账请及时联系客服人员为您处理。感谢您的支持与信任</string>
<string name="AlreadyKnown">已知晓</string>
<string name="DeleteStr">删除账号</string>
<string name="logOutStr"> 请注意! 删除账号之后将不能在使用该账号进行登录</string>
<string name="checkStr">请勾选复选框表明你同意删除账号</string>
</resources>