From 6c28512c1ae75b2fbd0d0589ddc483c1d76e9e31 Mon Sep 17 00:00:00 2001 From: tongtongstudio Date: Tue, 6 Jan 2026 09:34:39 +0800 Subject: [PATCH] =?UTF-8?q?version:1.2.0=20fix:=20update:=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E7=99=BB=E5=BD=95=E5=92=8C=E6=BF=80=E6=B4=BB=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/CMakeLists.txt | 44 ++ app/build.gradle | 16 +- app/src/main/AndroidManifest.xml | 27 +- .../activation/ActivationActivity.java | 48 ++ .../activation/ActivationViewModel.java | 7 +- .../xwad/os/activity/edit/EditActivity.java | 2 +- .../xwad/os/activity/home/HomeActivity.java | 66 ++- .../xwad/os/activity/home/HomeViewModel.java | 55 ++- .../xwad/os/activity/login/LoginActivity.java | 79 ++++ .../os/activity/login/LoginViewModel.java | 1 + .../login/result/LoginSuccessfulActivity.java | 23 +- .../xwad/os/activity/main/MainActivity.java | 7 - .../xwad/os/activity/user/UserActivity.java | 5 +- .../xwad/os/activity/user/UserViewModel.java | 39 ++ .../java/com/xwad/os/adapter/AppAdapter.java | 47 +- .../java/com/xwad/os/adapter/FileAdapter.java | 8 +- .../com/xwad/os/base/BaseApplication.java | 6 +- .../main/java/com/xwad/os/bean/OrderInfo.java | 9 + .../java/com/xwad/os/config/CommonConfig.java | 8 + .../com/xwad/os/dialog/PermissionsDialog.java | 14 + .../xwad/os/dialog/PrivacyPolicyDialog.java | 19 + .../xwad/os/fragment/app/AppViewModel.java | 15 +- .../os/fragment/chinese/ChineseFragment.java | 2 +- .../os/fragment/english/EnglishFragment.java | 16 +- .../xwad/os/fragment/math/MathFragment.java | 2 +- .../xwad/os/fragment/mine/MineFragment.java | 53 ++- .../xwad/os/fragment/mine/MineViewModel.java | 74 +++ .../xwad/os/fragment/safe/SafeFragment.java | 4 +- .../usercenter/account/AccountFragment.java | 39 +- .../usercenter/account/AccountViewModel.java | 34 ++ .../com/xwad/os/jxw/JxwPackageConfig.java | 3 + .../com/xwad/os/jxw/fragment/HxFragment.java | 2 +- .../com/xwad/os/jxw/fragment/SwFragment.java | 2 +- .../com/xwad/os/jxw/fragment/WlFragment.java | 2 +- .../main/java/com/xwad/os/jxw/util/Util.java | 3 +- .../xwad/os/network/NetInterfaceManager.java | 75 ++- .../java/com/xwad/os/network/UrlAddress.java | 14 +- .../com/xwad/os/network/api/LoginApi.java | 4 +- .../com/xwad/os/network/api/SnInfoApi.java | 19 +- .../com/xwad/os/network/api/jxw/JxwApi.java | 24 + .../java/com/xwad/os/push/PushManager.java | 14 + .../xwad/os/receiver/APKinstallReceiver.java | 24 - .../xwad/os/receiver/ApkInstallReceiver.java | 60 +++ .../com/xwad/os/service/DownloadService.java | 7 +- .../com/xwad/os/service/SocketService.java | 444 ++++++++++++------ .../com/xwad/os/service/main/MainService.java | 56 +++ .../com/xwad/os/utils/ActivationUtil.java | 12 +- .../main/java/com/xwad/os/utils/JxwUtils.java | 87 ++++ .../java/com/xwad/os/utils/OpenApkUtils.java | 49 +- .../xwad/os/view/jxw/widget/AppsDialog.java | 2 +- .../os/view/jxw/widget/DefaultAppsDialog.java | 41 +- app/src/main/jni/xuewang.cpp | 26 + .../res/drawable-nodpi/icon_jxw_aizndy.png | Bin 0 -> 40328 bytes .../res/drawable-nodpi/icon_jxw_launcher.png | Bin 0 -> 8190 bytes app/src/main/res/drawable/ic_download.xml | 9 + app/src/main/res/layout/activity_home.xml | 4 +- app/src/main/res/layout/activity_login.xml | 30 +- .../res/layout/activity_login_successful.xml | 4 +- .../main/res/layout/dialog_default_apps.xml | 11 + .../layout/fragment_dialog_login_statu.xml | 4 + app/src/main/res/layout/fragment_mine.xml | 70 ++- app/src/main/res/layout/item_dialog_app.xml | 31 +- app/src/main/res/layout/item_tab.xml | 4 +- app/src/main/res/values/string_jxw.xml | 1 + 64 files changed, 1570 insertions(+), 337 deletions(-) create mode 100644 app/CMakeLists.txt create mode 100644 app/src/main/java/com/xwad/os/network/api/jxw/JxwApi.java delete mode 100644 app/src/main/java/com/xwad/os/receiver/APKinstallReceiver.java create mode 100644 app/src/main/java/com/xwad/os/receiver/ApkInstallReceiver.java create mode 100644 app/src/main/java/com/xwad/os/utils/JxwUtils.java create mode 100644 app/src/main/jni/xuewang.cpp create mode 100644 app/src/main/res/drawable-nodpi/icon_jxw_aizndy.png create mode 100644 app/src/main/res/drawable-nodpi/icon_jxw_launcher.png create mode 100644 app/src/main/res/drawable/ic_download.xml diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt new file mode 100644 index 0000000..518f773 --- /dev/null +++ b/app/CMakeLists.txt @@ -0,0 +1,44 @@ +# For more information about using CMake with Android Studio, read the +# documentation: https://d.android.com/studio/projects/add-native-code.html + +# Sets the minimum version of CMake required to build the native library. + +cmake_minimum_required(VERSION 3.4.1) + +# Creates and names a library, sets it as either STATIC +# or SHARED, and provides the relative paths to its source code. +# You can define multiple libraries, and CMake builds them for you. +# Gradle automatically packages shared libraries with your APK. + +add_library( # Sets the name of the library. + xuewang + + # Sets the library as a shared library. + SHARED + + # Provides a relative path to your source file(s). + src/main/jni/xuewang.cpp) + +# Searches for a specified prebuilt library and stores the path as a +# variable. Because CMake includes system libraries in the search path by +# default, you only need to specify the name of the public NDK library +# you want to add. CMake verifies that the library exists before +# completing its build. + +find_library( # Sets the name of the path variable. + log-lib + + # Specifies the name of the NDK library that + # you want CMake to locate. + log) + +# Specifies libraries CMake should link to your target library. You +# can link multiple libraries, such as libraries you define in this +# build script, prebuilt third-party libraries, or system libraries. + +target_link_libraries( # Specifies the target library. + xuewang + + # Links the target library to the log library + # included in the NDK. + ${log-lib}) \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 5452259..d886167 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,8 +16,8 @@ android { minSdkVersion 24 targetSdkVersion 29 - versionCode 14 - versionName "1.1.3" + versionCode 21 + versionName "1.2.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" @@ -32,12 +32,10 @@ android { ndk { //根据需要 自行选择添加的对应cpu类型的.so库。 - abiFilters 'armeabi', 'armeabi-v7a', 'arm64-v8a' - // 还可以添加 'x86', 'x86_64', 'mips', 'mips64' + abiFilters 'armeabi-v7a', 'arm64-v8a' + // 还可以添加 'armeabi', 'x86', 'x86_64', 'mips', 'mips64' } - buildConfigField "String", "WEBSOCKET_URL", '"wss://led.aolelearn.com/wss/device"' - dataBinding { enabled true } @@ -63,6 +61,11 @@ android { } } + externalNativeBuild { + cmake { + path file('CMakeLists.txt') + } + } signingConfigs { tuixin { @@ -123,6 +126,7 @@ android { } } } + } dependencies { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 7eef5c4..86bdb75 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -262,6 +262,19 @@ + + + + + + + + + + + @@ -286,18 +300,7 @@ - - - - - - - - - - - @@ -313,7 +316,7 @@ android:exported="true" /> diff --git a/app/src/main/java/com/xwad/os/activity/activation/ActivationActivity.java b/app/src/main/java/com/xwad/os/activity/activation/ActivationActivity.java index 8f1ba55..4b9883c 100644 --- a/app/src/main/java/com/xwad/os/activity/activation/ActivationActivity.java +++ b/app/src/main/java/com/xwad/os/activity/activation/ActivationActivity.java @@ -1,5 +1,6 @@ package com.xwad.os.activity.activation; +import android.content.Intent; import android.graphics.Bitmap; import android.text.Editable; import android.text.InputFilter; @@ -11,6 +12,8 @@ import androidx.lifecycle.Observer; import com.hjq.toast.Toaster; import com.xwad.os.R; +import com.xwad.os.activity.home.HomeActivity; +import com.xwad.os.activity.login.result.LoginSuccessfulActivity; import com.xwad.os.base.mvvm.BaseMvvmActivity; import com.xwad.os.bean.OrderInfo; import com.xwad.os.bean.PayInfo; @@ -21,9 +24,16 @@ import com.xwad.os.utils.BitmapUtils; import java.util.List; import java.util.Optional; +import java.util.concurrent.TimeUnit; + +import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; +import io.reactivex.rxjava3.core.Observable; +import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.schedulers.Schedulers; public class ActivationActivity extends BaseMvvmActivity { + private Disposable pollingDisposable; @Override protected int getLayoutId() { @@ -100,6 +110,12 @@ public class ActivationActivity extends BaseMvvmActivity() { + @Override + public void onChanged(Boolean aBoolean) { + finish(); + } + }); mViewModel.mPayInfoData.observe(this, new Observer() { @Override @@ -129,10 +145,42 @@ public class ActivationActivity extends BaseMvvmActivity { + // 此处执行轮询任务,例如网络请求 + mViewModel.getActivation(); + }, throwable -> { + // 处理错误 + throwable.printStackTrace(); + }); + } + + private void startHome() { + Intent intent = new Intent(ActivationActivity.this, HomeActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); + intent.setAction("show_activation_dialog"); + startActivity(intent); } public class BtnClick { diff --git a/app/src/main/java/com/xwad/os/activity/activation/ActivationViewModel.java b/app/src/main/java/com/xwad/os/activity/activation/ActivationViewModel.java index e8bb9bb..463b990 100644 --- a/app/src/main/java/com/xwad/os/activity/activation/ActivationViewModel.java +++ b/app/src/main/java/com/xwad/os/activity/activation/ActivationViewModel.java @@ -74,6 +74,7 @@ public class ActivationViewModel extends BaseViewModel mOrderInfoData = new MutableLiveData<>(); + public MutableLiveData mAlreadyActivatedData = new MutableLiveData<>(); public void getPayInfo(String vipId) { NetInterfaceManager.getInstance().getBuyVipControl(vipId) @@ -90,6 +91,10 @@ public class ActivationViewModel extends BaseViewModel= Build.VERSION_CODES.O) { + startForegroundService(intent); + } else { + startService(intent); + } + setWallpaper(); // ComponentName componentName = new ComponentName("com.jxw.hdhb", "com.jxw.hdhb.ui.activity.MainActivity"); // startActivity(new Intent().setComponent(componentName)); // startActivity(new Intent(HomeActivity.this, LoginActivity.class)); +// ComponentName componentName = new ComponentName(JxwPackageConfig.JXW_LAUNCHER_PACKAGE_NAME, JxwPackageConfig.JXW_LAUNCHER_CLASS_NAME); +// startService(new Intent().setComponent(componentName)); RemoteManager.setListener(this); Utils.getAndroiodScreenProperty(this); @@ -223,7 +233,9 @@ public class HomeActivity extends BaseMvvmActivity() { + @Override + public void onSubscribe(@NonNull Disposable d) { + Log.e("getOauthToken", "onSubscribe: "); + } + + @Override + public void onNext(@NonNull BaseResponse baseResponse) { + Log.e("getOauthToken", "onNext: " + baseResponse); + } + + @Override + public void onError(@NonNull Throwable e) { + Log.e("getOauthToken", "onError: " + e.getMessage()); + } + + @Override + public void onComplete() { + Log.e("getOauthToken", "onComplete: "); + } + }); + } + + public void getAnswerControlStatus() { + NetInterfaceManager.getInstance().getAnswerControlStatusControl() + .compose(RxLifecycle.bindUntilEvent(getLifecycle(), ActivityEvent.DESTROY)) + .subscribe(new Observer() { + @Override + public void onSubscribe(@NonNull Disposable d) { + Log.e("getAnswerControlStatus", "onSubscribe: "); + } + + @Override + public void onNext(@NonNull BaseResponse baseResponse) { + Log.e("getAnswerControlStatus", "onNext: " + baseResponse); + } + + @Override + public void onError(@NonNull Throwable e) { + Log.e("getAnswerControlStatus", "onError: " + e.getMessage()); + } + + @Override + public void onComplete() { + Log.e("getAnswerControlStatus", "onComplete: "); + } + }); + } } diff --git a/app/src/main/java/com/xwad/os/activity/login/LoginActivity.java b/app/src/main/java/com/xwad/os/activity/login/LoginActivity.java index ede7b85..e65ee18 100644 --- a/app/src/main/java/com/xwad/os/activity/login/LoginActivity.java +++ b/app/src/main/java/com/xwad/os/activity/login/LoginActivity.java @@ -4,18 +4,33 @@ import android.app.Activity; import android.content.Intent; import android.text.Editable; import android.text.TextUtils; +import android.util.Log; import android.view.View; import androidx.lifecycle.Observer; import com.hjq.toast.Toaster; +import com.trello.rxlifecycle4.RxLifecycle; +import com.trello.rxlifecycle4.android.ActivityEvent; import com.xwad.os.R; import com.xwad.os.base.mvvm.BaseMvvmActivity; import com.xwad.os.bean.LoginInfo; import com.xwad.os.databinding.ActivityLoginBinding; +import com.xwad.os.service.SocketService; + +import java.util.concurrent.TimeUnit; + +import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; +import io.reactivex.rxjava3.core.Observable; +import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.observers.DisposableObserver; +import io.reactivex.rxjava3.schedulers.Schedulers; public class LoginActivity extends BaseMvvmActivity { + + private Disposable mDisposable; + @Override protected int getLayoutId() { return R.layout.activity_login; @@ -40,24 +55,88 @@ public class LoginActivity extends BaseMvvmActivity() { + @Override + public void onChanged(Boolean aBoolean) { + if (aBoolean) { + Toaster.show("验证码发送成功"); + startCountdown(); + } else { + setCodeTextEnable(); + } + } + }); } + @Override + protected void onDestroy() { + super.onDestroy(); + if (mDisposable != null && !mDisposable.isDisposed()) { + mDisposable.dispose(); + mDisposable = null; + } + } + + private void startCountdown() { + int countdownTime = 60; // 倒计时总时长 + + mDisposable = Observable.interval(0, 1, TimeUnit.SECONDS) // 立即执行,间隔1秒 + .take(countdownTime + 1) // 总共发射的次数(从0开始,所以+1) + .map(aLong -> countdownTime - aLong) // 将递增序列转换为递减的剩余时间 + .subscribeOn(Schedulers.computation()) // 计时任务在计算线程执行 + .observeOn(AndroidSchedulers.mainThread()) // 结果回调到主线程更新UI + .compose(RxLifecycle.bindUntilEvent(getLifecycleSubject(), ActivityEvent.DESTROY)) + .subscribeWith(new DisposableObserver() { + @Override + public void onNext(Long remainingTime) { + Log.e("startCountdown", "onNext: " + remainingTime); + // 每秒更新UI,显示剩余时间 + mViewDataBinding.tvGetCode.setText(remainingTime + "秒"); + mViewDataBinding.tvGetCode.setEnabled(true);// 倒计时期间禁用按钮 + } + + @Override + public void onError(Throwable e) { + // 错误处理(通常很少发生) + Log.e("startCountdown", "Error: ", e); + onComplete(); + } + + @Override + public void onComplete() { + Log.e("startCountdown", "onComplete: "); + setCodeTextEnable(); + } + }); + } + + private void setCodeTextEnable() { + mViewDataBinding.tvGetCode.setText("获取"); + mViewDataBinding.tvGetCode.setEnabled(true); + } + public class BtnClick { public void getCode(View view) { + mViewDataBinding.tvGetCode.setText("发送中"); + mViewDataBinding.tvGetCode.setEnabled(false); Editable editable = mViewDataBinding.etMobile.getText(); if (editable == null) { Toaster.show("请输入手机号"); + setCodeTextEnable(); return; } String mobile = editable.toString(); if (TextUtils.isEmpty(mobile)) { Toaster.show("请输入手机号"); + setCodeTextEnable(); return; } mViewModel.getPhoneCode(mobile); diff --git a/app/src/main/java/com/xwad/os/activity/login/LoginViewModel.java b/app/src/main/java/com/xwad/os/activity/login/LoginViewModel.java index e83362e..b8e220f 100644 --- a/app/src/main/java/com/xwad/os/activity/login/LoginViewModel.java +++ b/app/src/main/java/com/xwad/os/activity/login/LoginViewModel.java @@ -56,6 +56,7 @@ public class LoginViewModel extends BaseViewModel { @@ -30,8 +33,24 @@ public class LoginSuccessfulActivity extends BaseMvvmActivity= Build.VERSION_CODES.O) { - startForegroundService(intent); - } else { - startService(intent); - } - // 全屏展示 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { diff --git a/app/src/main/java/com/xwad/os/activity/user/UserActivity.java b/app/src/main/java/com/xwad/os/activity/user/UserActivity.java index 5627ed7..2eae186 100644 --- a/app/src/main/java/com/xwad/os/activity/user/UserActivity.java +++ b/app/src/main/java/com/xwad/os/activity/user/UserActivity.java @@ -178,6 +178,7 @@ public class UserActivity extends BaseMvvmActivity params = new HashMap<>(); params.put("sn", NetInterfaceManager.convertToJsonRequestBody(DeviceSNManager.getDeviceSN())); - mViewModel.updateInfo(params, body); + mViewModel.updateAvatar(params, body); } else { mMMKV.encode(CommonConfig.UIUI_USER_AVATAR_KEY, avatarFilePath); } diff --git a/app/src/main/java/com/xwad/os/activity/user/UserViewModel.java b/app/src/main/java/com/xwad/os/activity/user/UserViewModel.java index 36f5b8b..abcfc28 100644 --- a/app/src/main/java/com/xwad/os/activity/user/UserViewModel.java +++ b/app/src/main/java/com/xwad/os/activity/user/UserViewModel.java @@ -139,5 +139,44 @@ public class UserViewModel extends BaseViewModel params, MultipartBody.Part multipartBody) { + if (!ActivationUtil.getInstance().isLogin()) { + return; + } + NetInterfaceManager.getInstance().getupdateAvatarObservable(params, multipartBody) + .compose(RxLifecycle.bindUntilEvent(getLifecycle(), ActivityEvent.DESTROY)) + .subscribe(new Observer() { + @Override + public void onSubscribe(@NonNull Disposable d) { + Log.e("updateInfo", "onSubscribe: "); + } + + @Override + public void onNext(@NonNull BaseResponse baseResponse) { + Log.e("updateInfo", "onNext: " + baseResponse); + if (baseResponse.code == 200) { + mSuccessfulData.setValue(true); + } else { + Toaster.show(baseResponse.msg); + mSuccessfulData.setValue(false); + } + } + + @Override + public void onError(@NonNull Throwable e) { + Log.e("updateInfo", "onError: " + e.getMessage()); + mSuccessfulData.setValue(false); + } + + @Override + public void onComplete() { + Log.e("updateInfo", "onComplete: "); + } + }); + + } + } diff --git a/app/src/main/java/com/xwad/os/adapter/AppAdapter.java b/app/src/main/java/com/xwad/os/adapter/AppAdapter.java index e8fa798..5e8fe7c 100644 --- a/app/src/main/java/com/xwad/os/adapter/AppAdapter.java +++ b/app/src/main/java/com/xwad/os/adapter/AppAdapter.java @@ -1,9 +1,8 @@ package com.xwad.os.adapter; -import android.app.Activity; import android.content.ComponentName; -import android.content.Context; import android.content.Intent; +import android.text.TextUtils; import android.util.Log; import android.view.LayoutInflater; import android.view.View; @@ -13,21 +12,25 @@ import android.widget.TextView; import androidx.annotation.NonNull; import androidx.constraintlayout.widget.ConstraintLayout; +import androidx.fragment.app.FragmentActivity; import androidx.recyclerview.widget.RecyclerView; import com.hjq.toast.Toaster; +import com.tencent.mmkv.MMKV; import com.xwad.os.BuildConfig; import com.xwad.os.R; import com.xwad.os.activity.ExitActivity; import com.xwad.os.activity.ManualActivity; import com.xwad.os.activity.PasswordActivity; +import com.xwad.os.activity.activation.ActivationActivity; +import com.xwad.os.activity.login.LoginActivity; import com.xwad.os.activity.service.ServiceActivity; import com.xwad.os.bean.DesktopIcon; +import com.xwad.os.config.CommonConfig; import com.xwad.os.manager.AppManager; import com.xwad.os.manager.RemoteManager; +import com.xwad.os.utils.ActivationUtil; import com.xwad.os.utils.ApkUtils; -import com.xwad.os.utils.BitmapUtils; -import com.xwad.os.utils.IconUtils; import com.xwad.os.utils.OpenApkUtils; import com.xwad.os.utils.Utils; @@ -38,14 +41,16 @@ import me.jessyan.autosize.AutoSizeCompat; public class AppAdapter extends RecyclerView.Adapter { private static final String TAG = "AppAdapter"; - private Context mContext; + private MMKV mMMKV = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE); + + private FragmentActivity mContext; private List desktopIcons; @NonNull @Override public AppHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - mContext = parent.getContext(); + mContext = (FragmentActivity) parent.getContext(); AutoSizeCompat.autoConvertDensityOfGlobal(mContext.getResources()); return new AppHolder(LayoutInflater.from(mContext).inflate(R.layout.item_app, parent, false)); } @@ -87,6 +92,32 @@ public class AppAdapter extends RecyclerView.Adapter { holder.root.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { + Log.e(TAG, "onClick: " + pkg); + if (TextUtils.isEmpty(pkg)) { + Toaster.show("应用未安装"); + OpenApkUtils.getInstance().showDownloadDialog(mContext, pkg, lable); + return; + } + + if (!ApkUtils.isAvailable(mContext, pkg)) { + OpenApkUtils.getInstance().showDownloadDialog(mContext, pkg, lable); + return; + } + + if (!BuildConfig.DEBUG) { + if (!ActivationUtil.getInstance().isLogin()) { + Toaster.show("请先登录"); + mContext.startActivity(new Intent(mContext, LoginActivity.class)); + return; + } + + if (!ActivationUtil.getInstance().isActivation()) { + Toaster.show("请先激活后使用"); + mContext.startActivity(new Intent(mContext, ActivationActivity.class)); + return; + } + } + switch (pkg) { case AppManager.ADD_NAME: mContext.startActivity(new Intent(mContext, PasswordActivity.class)); @@ -121,7 +152,7 @@ public class AppAdapter extends RecyclerView.Adapter { exitDesktop(); break; default: - boolean settingOtherAppInstaller = RemoteManager.getInstance().showThirdApp(); + boolean settingOtherAppInstaller = mMMKV.decodeInt(CommonConfig.APP_INSTALLATION, 1) == 1; if (!settingOtherAppInstaller && !ApkUtils.isSystemApp(mContext, desktopIcon.getPackageName())) { Toaster.show("已禁止应用打开"); } else { @@ -143,7 +174,7 @@ public class AppAdapter extends RecyclerView.Adapter { if (is_activation) { mContext.startActivity(new Intent(mContext, ExitActivity.class)); } else { - Utils.exitDesktop((Activity) mContext); + Utils.exitDesktop(mContext); } } diff --git a/app/src/main/java/com/xwad/os/adapter/FileAdapter.java b/app/src/main/java/com/xwad/os/adapter/FileAdapter.java index d1efbb6..f93c270 100644 --- a/app/src/main/java/com/xwad/os/adapter/FileAdapter.java +++ b/app/src/main/java/com/xwad/os/adapter/FileAdapter.java @@ -15,14 +15,15 @@ import androidx.constraintlayout.widget.ConstraintLayout; import androidx.recyclerview.widget.RecyclerView; import com.hjq.toast.Toaster; +import com.tencent.mmkv.MMKV; import com.xwad.os.BuildConfig; import com.xwad.os.R; import com.xwad.os.activity.ManualActivity; import com.xwad.os.activity.PasswordActivity; import com.xwad.os.activity.service.ServiceActivity; import com.xwad.os.bean.DesktopIcon; +import com.xwad.os.config.CommonConfig; import com.xwad.os.manager.AppManager; -import com.xwad.os.manager.RemoteManager; import com.xwad.os.utils.ApkUtils; import com.xwad.os.utils.BitmapUtils; import com.xwad.os.utils.IconUtils; @@ -33,8 +34,9 @@ import java.util.List; public class FileAdapter extends RecyclerView.Adapter { private static final String TAG = "FileAdapter"; - private Context mContext; + private MMKV mMMKV = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE); + private Context mContext; private List desktopIcons; @NonNull @@ -98,7 +100,7 @@ public class FileAdapter extends RecyclerView.Adapter { OpenApkUtils.getInstance().openApp(desktopIcon.getPackageName(), desktopIcon.getClassName()); break; default: - boolean settingOtherAppInstaller = RemoteManager.getInstance().showThirdApp(); + boolean settingOtherAppInstaller = mMMKV.decodeInt(CommonConfig.APP_INSTALLATION, 1) == 1; if (!settingOtherAppInstaller && !ApkUtils.isSystemApp(mContext, desktopIcon.getPackageName())) { Toaster.show("已禁止应用打开"); } else { diff --git a/app/src/main/java/com/xwad/os/base/BaseApplication.java b/app/src/main/java/com/xwad/os/base/BaseApplication.java index 5521696..10fd000 100644 --- a/app/src/main/java/com/xwad/os/base/BaseApplication.java +++ b/app/src/main/java/com/xwad/os/base/BaseApplication.java @@ -27,7 +27,7 @@ import com.xwad.os.manager.DeviceSNManager; import com.xwad.os.manager.RemoteManager; import com.xwad.os.network.NetInterfaceManager; import com.xwad.os.push.PushManager; -import com.xwad.os.receiver.APKinstallReceiver; +import com.xwad.os.receiver.ApkInstallReceiver; import com.xwad.os.utils.ActivationUtil; import com.xwad.os.utils.AppUsedTimeUtils; import com.xwad.os.utils.LenovoCsdkUtil; @@ -129,11 +129,11 @@ public class BaseApplication extends Application { }); } - private APKinstallReceiver apKinstallReceiver; + private ApkInstallReceiver apKinstallReceiver; private void registAppReceive() { if (null == apKinstallReceiver) { - apKinstallReceiver = new APKinstallReceiver(); + apKinstallReceiver = new ApkInstallReceiver(); } IntentFilter filter = new IntentFilter(); filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); diff --git a/app/src/main/java/com/xwad/os/bean/OrderInfo.java b/app/src/main/java/com/xwad/os/bean/OrderInfo.java index fad8a8b..d0de43f 100644 --- a/app/src/main/java/com/xwad/os/bean/OrderInfo.java +++ b/app/src/main/java/com/xwad/os/bean/OrderInfo.java @@ -14,6 +14,7 @@ public class OrderInfo implements Serializable { String order_sn; String sn; String vip_level_id; + int is_old; public int getOrder_id() { return order_id; @@ -47,6 +48,14 @@ public class OrderInfo implements Serializable { this.vip_level_id = vip_level_id; } + public int getIs_old() { + return is_old; + } + + public void setIs_old(int is_old) { + this.is_old = is_old; + } + @NonNull @Override public String toString() { diff --git a/app/src/main/java/com/xwad/os/config/CommonConfig.java b/app/src/main/java/com/xwad/os/config/CommonConfig.java index ca9f0b4..1e76ce0 100644 --- a/app/src/main/java/com/xwad/os/config/CommonConfig.java +++ b/app/src/main/java/com/xwad/os/config/CommonConfig.java @@ -72,4 +72,12 @@ public class CommonConfig { public static final String ACCOUNT_DEVICE_ID = "account_device_id_key"; public static final String ACCOUNT_DEVICE_SN = "account_device_sn_key"; + + /*应用市场是否禁止下载*/ + public static final String APP_STORE_INSTALL = "iflytek_setting_is_storeinstall"; + /*是否禁止应用打开*/ + public static final String APP_INSTALLATION = "iflytek_setting_other_appInstaller"; + /*是否为管理员app*/ + public static final String APP_ADMIN = "iflytek_setting_admin_app"; + } diff --git a/app/src/main/java/com/xwad/os/dialog/PermissionsDialog.java b/app/src/main/java/com/xwad/os/dialog/PermissionsDialog.java index ed668fd..e7405b3 100644 --- a/app/src/main/java/com/xwad/os/dialog/PermissionsDialog.java +++ b/app/src/main/java/com/xwad/os/dialog/PermissionsDialog.java @@ -3,13 +3,17 @@ package com.xwad.os.dialog; import android.content.Context; import android.os.Bundle; import android.text.TextUtils; +import android.view.Gravity; import android.view.View; +import android.view.Window; +import android.view.WindowManager; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; +import com.blankj.utilcode.util.ScreenUtils; import com.xwad.os.R; public class PermissionsDialog extends AlertDialog { @@ -101,6 +105,16 @@ public class PermissionsDialog extends AlertDialog { @Override public void show() { super.show(); + // 获取对话框的 Window 对象 + Window dialogWindow = getWindow(); + if (dialogWindow != null) { + WindowManager.LayoutParams params = dialogWindow.getAttributes(); + // 设置宽度为屏幕宽度的95%,这能有效解决在Android 9.0+上的偏移问题 + params.width = (int) (ScreenUtils.getScreenWidth() * 0.95); + // 确保重力设置为居中 + params.gravity = Gravity.CENTER; + dialogWindow.setAttributes(params); + } setText(); } diff --git a/app/src/main/java/com/xwad/os/dialog/PrivacyPolicyDialog.java b/app/src/main/java/com/xwad/os/dialog/PrivacyPolicyDialog.java index a014c69..dbc1e24 100644 --- a/app/src/main/java/com/xwad/os/dialog/PrivacyPolicyDialog.java +++ b/app/src/main/java/com/xwad/os/dialog/PrivacyPolicyDialog.java @@ -10,13 +10,17 @@ import android.text.Spanned; import android.text.method.LinkMovementMethod; import android.text.style.ClickableSpan; import android.text.style.ForegroundColorSpan; +import android.view.Gravity; import android.view.View; +import android.view.Window; +import android.view.WindowManager; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; +import com.blankj.utilcode.util.ScreenUtils; import com.xwad.os.R; import com.xwad.os.activity.privacy.PrivacyActivity; @@ -107,4 +111,19 @@ public class PrivacyPolicyDialog extends AlertDialog { } }); } + + @Override + public void show() { + super.show(); + // 获取对话框的 Window 对象 + Window dialogWindow = getWindow(); + if (dialogWindow != null) { + WindowManager.LayoutParams params = dialogWindow.getAttributes(); + // 设置宽度为屏幕宽度的95%,这能有效解决在Android 9.0+上的偏移问题 + params.width = (int) (ScreenUtils.getScreenWidth() * 0.95); + // 确保重力设置为居中 + params.gravity = Gravity.CENTER; + dialogWindow.setAttributes(params); + } + } } diff --git a/app/src/main/java/com/xwad/os/fragment/app/AppViewModel.java b/app/src/main/java/com/xwad/os/fragment/app/AppViewModel.java index 4b65793..efac11f 100644 --- a/app/src/main/java/com/xwad/os/fragment/app/AppViewModel.java +++ b/app/src/main/java/com/xwad/os/fragment/app/AppViewModel.java @@ -104,27 +104,34 @@ public class AppViewModel extends BaseViewModel() { + @Override + public void onChanged(UserAvatarInfo userAvatarInfo) { + mViewDataBinding.setUserAvatarInfo(userAvatarInfo); + } + }); + mViewModel.getSnInfo(); } @Override @@ -222,6 +209,12 @@ public class MineFragment extends BaseMvvmFragment { @Override @@ -15,4 +29,64 @@ public class MineViewModel extends BaseViewModel mUserAvatarInfoData = new MutableLiveData<>(); + + public void getUserAvatarInfo() { + NetInterfaceManager.getInstance() + .getUserAvatarInfoControl() + .compose(RxLifecycle.bindUntilEvent(getLifecycle(), FragmentEvent.DESTROY)) + .subscribe(new Observer>() { + @Override + public void onSubscribe(@NonNull Disposable d) { + Log.e("getUserAvatarInfo", "onSubscribe: "); + } + + @Override + public void onNext(@NonNull BaseResponse userAvatarInfoBaseResponse) { + Log.e("getUserAvatarInfo", "onNext: " + userAvatarInfoBaseResponse); + mUserAvatarInfoData.setValue(userAvatarInfoBaseResponse.data); + } + + @Override + public void onError(@NonNull Throwable e) { + Log.e("getUserAvatarInfo", "onError: " + e.getMessage()); + } + + @Override + public void onComplete() { + Log.e("getUserAvatarInfo", "onComplete: "); + } + }); + } + + public MutableLiveData mSnInfoData = new MutableLiveData<>(); + + public void getSnInfo() { + NetInterfaceManager.getInstance().getSnInfoControl() + .compose(RxLifecycle.bindUntilEvent(getLifecycle(), FragmentEvent.DESTROY)) + .subscribe(new Observer>() { + @Override + public void onSubscribe(@NonNull Disposable d) { + Log.e("getSnInfo", "onSubscribe: "); + } + + @Override + public void onNext(@NonNull BaseResponse snInfoBaseResponse) { + Log.e("getSnInfo", "onNext: " + snInfoBaseResponse); + if (snInfoBaseResponse.code == 200) { + mSnInfoData.setValue(snInfoBaseResponse.data); + } + } + + @Override + public void onError(@NonNull Throwable e) { + Log.e("getSnInfo", "onError: "); + } + + @Override + public void onComplete() { + Log.e("getSnInfo", "onComplete: "); + } + }); + } } diff --git a/app/src/main/java/com/xwad/os/fragment/safe/SafeFragment.java b/app/src/main/java/com/xwad/os/fragment/safe/SafeFragment.java index 68a044b..d5c81ba 100644 --- a/app/src/main/java/com/xwad/os/fragment/safe/SafeFragment.java +++ b/app/src/main/java/com/xwad/os/fragment/safe/SafeFragment.java @@ -17,12 +17,10 @@ import androidx.recyclerview.widget.GridLayoutManager; import com.chad.library.adapter.base.BaseQuickAdapter; import com.tencent.mmkv.MMKV; import com.xwad.os.R; -import com.xwad.os.adapter.AppAdapter; import com.xwad.os.base.mvvm.fragment.BaseMvvmFragment; import com.xwad.os.bean.jxw.AppInfo; import com.xwad.os.config.CommonConfig; import com.xwad.os.databinding.FragmentSafeBinding; -import com.xwad.os.jxw.AssertUtils; import com.xwad.os.jxw.StudyRecordMng; import com.xwad.os.jxw.ToastUtil; import com.xwad.os.jxw.adapter.ZhMenuAdapter; @@ -164,7 +162,7 @@ public class SafeFragment extends BaseMvvmFragment { @@ -112,6 +115,31 @@ public class AccountFragment extends BaseMvvmFragment mActivationLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback() { + @Override + public void onActivityResult(ActivityResult result) { + Log.e(TAG, "onActivityResult: " + result); + if (result != null) { + Intent intent = result.getData(); + if (intent != null && result.getResultCode() == Activity.RESULT_OK) { + mViewModel.getUserInfo(); + + DefaultAppsDialog appsDialog = new DefaultAppsDialog(getActivity()); + appsDialog.show(); } } } @@ -190,7 +218,14 @@ public class AccountFragment extends BaseMvvmFragment>() { + @Override + public void onSubscribe(@NonNull Disposable d) { + Log.e("getAppInfo", "onSubscribe: "); + } + + @Override + public void onNext(@NonNull BaseResponse baseResponse) { + Log.e("getAppInfo", "onNext: " + baseResponse); + if (baseResponse.code == 200) { + AppInfo appInfo = baseResponse.data; + FileUtil.ariaDownload(getCtx(), appInfo.getApp_url(), appInfo); + } else { + Toaster.showLong("没有找到应用信息,请联系客服"); + } + } + + @Override + public void onError(@NonNull Throwable e) { + Log.e("getAppInfo", "onError: " + e.getMessage()); + } + + @Override + public void onComplete() { + Log.e("getAppInfo", "onComplete: "); + } + }); + } } diff --git a/app/src/main/java/com/xwad/os/jxw/JxwPackageConfig.java b/app/src/main/java/com/xwad/os/jxw/JxwPackageConfig.java index 64057a1..9d4f934 100644 --- a/app/src/main/java/com/xwad/os/jxw/JxwPackageConfig.java +++ b/app/src/main/java/com/xwad/os/jxw/JxwPackageConfig.java @@ -3,6 +3,9 @@ package com.xwad.os.jxw; public class JxwPackageConfig { /*注册桌面*/ public static final String JXW_LAUNCHER_PACKAGE_NAME = "com.jxw.launcher"; + public static final String JXW_LAUNCHER_REGISTER_CLASS_NAME = "com.jxw.engine.platsign.MainActivity"; + public static final String JXW_LAUNCHER_DUMMY_ACTIVITY = "com.jxw.launcher.DummyActivity"; + public static final String JXW_LAUNCHER_CLASS_NAME = "com.jht.engine.platsign.PlatformService"; public static final String JXW_LAUNCHER_UPDATE_CLASS_NAME = "com.jxw.engine.platsign.UpdateActivity"; /*同步视频*/ diff --git a/app/src/main/java/com/xwad/os/jxw/fragment/HxFragment.java b/app/src/main/java/com/xwad/os/jxw/fragment/HxFragment.java index fb0183f..3f43da7 100644 --- a/app/src/main/java/com/xwad/os/jxw/fragment/HxFragment.java +++ b/app/src/main/java/com/xwad/os/jxw/fragment/HxFragment.java @@ -216,7 +216,7 @@ public class HxFragment extends BaseNewFragment { contentAdapter.notifyDataSetChanged(); // MyApp.getInstance().mBottomBtnOnClickListener.setContext(getActivity()); // MyApp.getInstance().mBottomBtnOnClickListener.onClick(obj); - OpenApkUtils.getInstance().openJxwApp(getActivity(), obj); + OpenApkUtils.getInstance().openJxwAppWithParam(getActivity(), obj, true); } private void saveTag(ItemsBean itemsBean) { diff --git a/app/src/main/java/com/xwad/os/jxw/fragment/SwFragment.java b/app/src/main/java/com/xwad/os/jxw/fragment/SwFragment.java index 749e512..84dae03 100644 --- a/app/src/main/java/com/xwad/os/jxw/fragment/SwFragment.java +++ b/app/src/main/java/com/xwad/os/jxw/fragment/SwFragment.java @@ -223,7 +223,7 @@ public class SwFragment extends BaseNewFragment { contentAdapter.notifyDataSetChanged(); // MyApp.getInstance().mBottomBtnOnClickListener.setContext(getActivity()); // MyApp.getInstance().mBottomBtnOnClickListener.onClick(obj); - OpenApkUtils.getInstance().openJxwApp(getActivity(), obj); + OpenApkUtils.getInstance().openJxwAppWithParam(getActivity(), obj, true); } private void saveTag(ItemsBean itemsBean) { diff --git a/app/src/main/java/com/xwad/os/jxw/fragment/WlFragment.java b/app/src/main/java/com/xwad/os/jxw/fragment/WlFragment.java index d20f6ae..766cce3 100644 --- a/app/src/main/java/com/xwad/os/jxw/fragment/WlFragment.java +++ b/app/src/main/java/com/xwad/os/jxw/fragment/WlFragment.java @@ -222,7 +222,7 @@ public class WlFragment extends BaseNewFragment { contentAdapter.notifyDataSetChanged(); // MyApp.getInstance().mBottomBtnOnClickListener.setContext(getActivity()); // MyApp.getInstance().mBottomBtnOnClickListener.onClick(obj); - OpenApkUtils.getInstance().openJxwApp(getActivity(), obj); + OpenApkUtils.getInstance().openJxwAppWithParam(getActivity(), obj, true); } private void saveTag(ItemsBean itemsBean) { diff --git a/app/src/main/java/com/xwad/os/jxw/util/Util.java b/app/src/main/java/com/xwad/os/jxw/util/Util.java index 30e86d7..88f3b53 100644 --- a/app/src/main/java/com/xwad/os/jxw/util/Util.java +++ b/app/src/main/java/com/xwad/os/jxw/util/Util.java @@ -56,7 +56,8 @@ public class Util { } public static void downloadClickListener(Activity activity, String str, String str2, String str3, String str4) { - OpenApkUtils.getInstance().openJxwApp(activity, "" + str + "," + str2 + "," + str3 + "," + str.substring(str.lastIndexOf(".") + 1) + "," + str4); + String tag = "" + str + "," + str2 + "," + str3 + "," + str.substring(str.lastIndexOf(".") + 1) + "," + str4; + OpenApkUtils.getInstance().openJxwAppWithParam(activity, tag, true); } public static String checkGrade(String str) { diff --git a/app/src/main/java/com/xwad/os/network/NetInterfaceManager.java b/app/src/main/java/com/xwad/os/network/NetInterfaceManager.java index c966458..a0fb998 100644 --- a/app/src/main/java/com/xwad/os/network/NetInterfaceManager.java +++ b/app/src/main/java/com/xwad/os/network/NetInterfaceManager.java @@ -36,7 +36,6 @@ import com.xwad.os.config.CommonConfig; import com.xwad.os.disklrucache.CacheHelper; import com.xwad.os.gson.GsonUtils; import com.xwad.os.manager.DeviceSNManager; -import com.xwad.os.manager.RemoteManager; import com.xwad.os.network.api.AlarmClockApi; import com.xwad.os.network.api.AppApi; import com.xwad.os.network.api.AppUsageRecordApi; @@ -44,18 +43,21 @@ import com.xwad.os.network.api.FilesApi; import com.xwad.os.network.api.HomeworkApi; import com.xwad.os.network.api.LoginApi; import com.xwad.os.network.api.PhraseApi; -import com.xwad.os.network.api.SnInfoApi; import com.xwad.os.network.api.SettingApi; +import com.xwad.os.network.api.SnInfoApi; import com.xwad.os.network.api.UserApi; +import com.xwad.os.network.api.jxw.JxwApi; import com.xwad.os.network.api.uiuios.CheckUpdateApi; import com.xwad.os.network.interceptor.RepeatRequestInterceptor; -import com.xwad.os.utils.LenovoCsdkUtil; +import com.xwad.os.utils.ActivationUtil; +import com.xwad.os.utils.JxwUtils; import com.xwad.os.utils.OpenApkUtils; import com.xwad.os.utils.Utils; import java.io.File; import java.lang.reflect.Type; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -92,6 +94,8 @@ public class NetInterfaceManager { private OkHttpClient mOkHttpClient; private Retrofit mUiuiosRetrofit; private OkHttpClient mUiuiosOkHttpClient; + private Retrofit mJxwRetrofit; + private OkHttpClient mJxwOkHttpClient; private final ConcurrentHashMap requestIdsMap = new ConcurrentHashMap<>(); //超时时间 @@ -106,7 +110,6 @@ public class NetInterfaceManager { this.mContext = context; this.mCacheHelper = new CacheHelper(context); if (mOkHttpClient == null) { - //如果无法生存缓存文件目录,检测权限使用已经加上,检测手机是否把文件读写权限禁止了 OkHttpClient.Builder builder = new OkHttpClient.Builder(); builder.connectTimeout(TIME_OUT, TimeUnit.SECONDS); // 设置连接超时时间 @@ -131,7 +134,6 @@ public class NetInterfaceManager { } if (mUiuiosOkHttpClient == null) { - //如果无法生存缓存文件目录,检测权限使用已经加上,检测手机是否把文件读写权限禁止了 OkHttpClient.Builder builder = new OkHttpClient.Builder(); builder.connectTimeout(TIME_OUT, TimeUnit.SECONDS); // 设置连接超时时间 @@ -154,6 +156,30 @@ public class NetInterfaceManager { .addCallAdapterFactory(RxJava3CallAdapterFactory.create()) .build(); } + + if (mJxwOkHttpClient == null) { + //如果无法生存缓存文件目录,检测权限使用已经加上,检测手机是否把文件读写权限禁止了 + OkHttpClient.Builder builder = new OkHttpClient.Builder(); + builder.connectTimeout(TIME_OUT, TimeUnit.SECONDS); // 设置连接超时时间 + builder.writeTimeout(TIME_OUT, TimeUnit.SECONDS);// 设置写入超时时间 + builder.readTimeout(TIME_OUT, TimeUnit.SECONDS);// 设置读取数据超时时间 + builder.retryOnConnectionFailure(true);// 设置进行连接失败重试 + builder.addInterceptor(new RepeatRequestInterceptor()); + + // 设置缓存文件路径 + Cache cache = new Cache(new File(Utils.getCacheDir(mContext) + "/OkHttpCache"), CACHE_SIZE); + builder.cache(cache);// 设置缓存 + mJxwOkHttpClient = builder.build(); + } + + if (mJxwRetrofit == null) { + mJxwRetrofit = new Retrofit.Builder() + .client(mJxwOkHttpClient) + .baseUrl(UrlAddress.JXW_BASE_URL) + .addConverterFactory(GsonConverterFactory.create()) + .addCallAdapterFactory(RxJava3CallAdapterFactory.create()) + .build(); + } } /** @@ -206,7 +232,7 @@ public class NetInterfaceManager { } - private String getToken() { + public String getToken() { String token = mMMKV.decodeString(CommonConfig.ACCOUNT_LOGIN_TOKEN, ""); return token; } @@ -257,14 +283,21 @@ public class NetInterfaceManager { String json = GsonUtils.toJSONString(params); RequestBody body = convertToJsonRequestBody(json); return mRetrofit.create(SnInfoApi.class) - .updateUserInfo(body) + .updateUserInfo(getToken(), body) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); } public Observable getUpdateInfoObservable(Map params, MultipartBody.Part multipartBody) { return mRetrofit.create(SnInfoApi.class) - .updateUserInfo(params, multipartBody) + .updateUserInfo(getToken(), params, multipartBody) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()); + } + + public Observable getupdateAvatarObservable(Map params, MultipartBody.Part multipartBody) { + return mRetrofit.create(SnInfoApi.class) + .updateAvatar(getToken(), params, multipartBody) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); } @@ -314,7 +347,7 @@ public class NetInterfaceManager { public Observable getUpdateAddressObservable(String address, double longitude, double latitude) { return mRetrofit.create(SnInfoApi.class) - .updateAddress(DeviceSNManager.getDeviceSN(), address, longitude, latitude) + .updateAddress(getToken(), DeviceSNManager.getDeviceSN(), address, longitude, latitude) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); } @@ -384,7 +417,7 @@ public class NetInterfaceManager { public Observable> getNewCodeLoginObservable(String mobile, String code) { return mRetrofit.create(LoginApi.class) - .newCodeLogin(mobile, code) + .newCodeLogin(mobile, code, "", BuildConfig.APPLICATION_ID) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); } @@ -438,6 +471,28 @@ public class NetInterfaceManager { .observeOn(AndroidSchedulers.mainThread()); } + public Observable getOauthTokenObservable() { + Map params = new HashMap<>(); + params.put("appId", JxwUtils.getAppId()); + params.put("signature", JxwUtils.getAppSecret()); + params.put("timestamp", String.valueOf(System.currentTimeMillis())); + params.put("nonce", "zylcpxlj"); + return mJxwRetrofit.create(JxwApi.class) + .getOauthToken(params) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()); + } + + public Observable getAnswerControlStatusControl() { + Map params = new HashMap<>(); + params.put("deviceSeries", ActivationUtil.getInstance().getActivationCode()); + params.put("registerIsbn", "zylcpxlj"); + return mJxwRetrofit.create(JxwApi.class) + .getAnswerControlStatus(JxwUtils.getSignature(params), params) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()); + } + /* * diff --git a/app/src/main/java/com/xwad/os/network/UrlAddress.java b/app/src/main/java/com/xwad/os/network/UrlAddress.java index 6be1cd2..75bdd63 100644 --- a/app/src/main/java/com/xwad/os/network/UrlAddress.java +++ b/app/src/main/java/com/xwad/os/network/UrlAddress.java @@ -3,6 +3,9 @@ package com.xwad.os.network; public class UrlAddress { public static final String ROOT_URL = "https://365api.uiuipad.com/android/"; + public static final String WEBSOCKET_URL_ONLINE = "wss://365api.uiuipad.com/wss/device"; + public static final String WEBSOCKET_URL_SSO = "wss://365api.uiuipad.com/wss/sso"; + /*发送登录验证码*/ public final static String LOGIN_GET_CODE = "login/get-code"; @@ -36,13 +39,14 @@ public class UrlAddress { public final static String APP_FORCE_INSTALL = "app/force-install"; - /*设备信息接口*/ public static final String SNINFO = "sn/getSnInfo"; /*获取用户头像和信息*/ public static final String GET_USER_AVATAR_INFO = "sn/getUserAvatarInfo"; /*修改设备个人信息*/ public static final String UPDATE_INFO = "sn/update-info"; + /*更新头像*/ + public static final String UPDATE_avatar = "sn/avatar"; /*获取统计*/ public static final String GET_STUDY_STAT = "Sn/getStudyStat"; @@ -81,4 +85,12 @@ public class UrlAddress { public static final String UIUIOS_ROOT_URL = "https://map.uiuios.com/android/"; /*获取应用更新*/ public static final String CHECK_UPDATE = "app/check-update"; + + public static final String JXW_BASE_URL = "https://openapi.jxwxxkj.com/"; + /*第三方登录-获取openToken*/ + public static final String get_oauth_token = "auth2/api/oauth/token"; + /*控制/设备端-查看答疑管控状态*/ + public static final String answer_Control_status = "api/jxwdevice/answerControl/status"; + + } diff --git a/app/src/main/java/com/xwad/os/network/api/LoginApi.java b/app/src/main/java/com/xwad/os/network/api/LoginApi.java index ce758c3..f26b7d0 100644 --- a/app/src/main/java/com/xwad/os/network/api/LoginApi.java +++ b/app/src/main/java/com/xwad/os/network/api/LoginApi.java @@ -37,6 +37,8 @@ public interface LoginApi { @POST(UrlAddress.NEW_CODE_LOGIN) Observable> newCodeLogin( @Field("mobile") String mobile, - @Field("code") String code + @Field("code") String code, + @Field("sn") String sn, + @Field("desktop_package") String desktop_package ); } diff --git a/app/src/main/java/com/xwad/os/network/api/SnInfoApi.java b/app/src/main/java/com/xwad/os/network/api/SnInfoApi.java index 09e3760..77e48fe 100644 --- a/app/src/main/java/com/xwad/os/network/api/SnInfoApi.java +++ b/app/src/main/java/com/xwad/os/network/api/SnInfoApi.java @@ -15,6 +15,7 @@ import retrofit2.http.Body; import retrofit2.http.Field; import retrofit2.http.FormUrlEncoded; import retrofit2.http.GET; +import retrofit2.http.Header; import retrofit2.http.Multipart; import retrofit2.http.POST; import retrofit2.http.Part; @@ -34,13 +35,26 @@ public interface SnInfoApi { ); @POST(UrlAddress.UPDATE_INFO) - Observable updateUserInfo(@Body RequestBody requestBody); + Observable updateUserInfo( + @Header("token") String token, + @Body RequestBody requestBody + ); @Multipart @POST(UrlAddress.UPDATE_INFO) Observable updateUserInfo( + @Header("token") String token, @PartMap Map params, - @Part MultipartBody.Part body); + @Part MultipartBody.Part body + ); + + @Multipart + @POST(UrlAddress.UPDATE_avatar) + Observable updateAvatar( + @Header("token") String token, + @PartMap Map params, + @Part MultipartBody.Part body + ); @GET(UrlAddress.GET_STUDY_STAT) Observable> getStudyStat( @@ -50,6 +64,7 @@ public interface SnInfoApi { @FormUrlEncoded @POST(UrlAddress.UPDATE_ADDRESS) Observable updateAddress( + @Header("token") String token, @Field("sn") String sn, @Field("address") String address, @Field("longitude") double longitude, diff --git a/app/src/main/java/com/xwad/os/network/api/jxw/JxwApi.java b/app/src/main/java/com/xwad/os/network/api/jxw/JxwApi.java new file mode 100644 index 0000000..a9b7c33 --- /dev/null +++ b/app/src/main/java/com/xwad/os/network/api/jxw/JxwApi.java @@ -0,0 +1,24 @@ +package com.xwad.os.network.api.jxw; + +import com.xwad.os.bean.BaseResponse; +import com.xwad.os.network.UrlAddress; + +import java.util.Map; + +import io.reactivex.rxjava3.core.Observable; +import retrofit2.http.GET; +import retrofit2.http.Header; +import retrofit2.http.QueryMap; + +public interface JxwApi { + @GET(UrlAddress.get_oauth_token) + Observable getOauthToken( + @QueryMap Map params + ); + + @GET(UrlAddress.answer_Control_status) + Observable getAnswerControlStatus( + @Header("token") String token, + @QueryMap Map params + ); +} diff --git a/app/src/main/java/com/xwad/os/push/PushManager.java b/app/src/main/java/com/xwad/os/push/PushManager.java index 3f1d0a2..be2a6ee 100644 --- a/app/src/main/java/com/xwad/os/push/PushManager.java +++ b/app/src/main/java/com/xwad/os/push/PushManager.java @@ -5,6 +5,7 @@ import android.content.ContentResolver; import android.content.Context; import android.content.Intent; +import com.xwad.os.activity.home.HomeActivity; import com.xwad.os.disklrucache.CacheHelper; import com.xwad.os.fragment.user.UserFragment; import com.xwad.os.network.NetInterfaceManager; @@ -48,6 +49,8 @@ public class PushManager { private static final String JIGUANG_ALARM_CLOCK = "57"; /*网课模式*/ private static final String ONLINE_COURSE_MODE = "71"; + /*付款成功*/ + private static final String WECHAT_PAY_COMPLETE = "97"; /*作业提醒*/ private static final String HOMEWORK_REMINDERS = "115"; /*爱的鼓励*/ @@ -64,6 +67,9 @@ public class PushManager { Toaster.debugShow("收到推送消息: 网课模式"); NetInterfaceManager.getInstance().getCloudLessonSettings(); break; + case WECHAT_PAY_COMPLETE: + startHome(); + break; case HOMEWORK_REMINDERS: sendHomework(extras); break; @@ -74,6 +80,14 @@ public class PushManager { } } + private void startHome() { + Intent intent = new Intent(mContext, HomeActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); + intent.setAction("show_activation_dialog"); + mContext.startActivity(intent); + } + private void sendAlarmClock(String extras) { NetInterfaceManager.getInstance().getAlarmClock(); Intent intent = new Intent(SET_ALARMCLOCK); diff --git a/app/src/main/java/com/xwad/os/receiver/APKinstallReceiver.java b/app/src/main/java/com/xwad/os/receiver/APKinstallReceiver.java deleted file mode 100644 index 3e0cd47..0000000 --- a/app/src/main/java/com/xwad/os/receiver/APKinstallReceiver.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.xwad.os.receiver; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.util.Log; - -import com.xwad.os.BuildConfig; -import com.xwad.os.fragment.user.UserFragment; - -public class APKinstallReceiver extends BroadcastReceiver { - - private static final String TAG = "APKinstallReceiver"; - - @Override - public void onReceive(final Context context, Intent intent) { - // an Intent broadcast. - String packageName = intent.getDataString().replace("package:", ""); - Log.e(TAG, "onReceive: " + packageName + ": " + intent.getAction()); - Intent updateIntent = new Intent(UserFragment.UPDATE_DESKTOP_ICON_ACTION); - intent.setPackage(BuildConfig.APPLICATION_ID); - context.sendBroadcast(updateIntent); - } -} diff --git a/app/src/main/java/com/xwad/os/receiver/ApkInstallReceiver.java b/app/src/main/java/com/xwad/os/receiver/ApkInstallReceiver.java new file mode 100644 index 0000000..c9f50e2 --- /dev/null +++ b/app/src/main/java/com/xwad/os/receiver/ApkInstallReceiver.java @@ -0,0 +1,60 @@ +package com.xwad.os.receiver; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.os.Handler; +import android.util.Log; + +import com.tencent.mmkv.MMKV; +import com.xwad.os.BuildConfig; +import com.xwad.os.config.CommonConfig; +import com.xwad.os.fragment.user.UserFragment; +import com.xwad.os.jxw.JxwPackageConfig; +import com.xwad.os.service.main.MainService; +import com.xwad.os.utils.ActivationUtil; + +public class ApkInstallReceiver extends BroadcastReceiver { + + private static final String TAG = "APKinstallReceiver"; + private MMKV mMMKV = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE); + + @Override + public void onReceive(final Context context, Intent intent) { + // an Intent broadcast. + String action = intent.getAction(); + + String packageName = intent.getDataString().replace("package:", ""); + Log.e(TAG, "onReceive: " + packageName + ": " + intent.getAction()); + + Intent updateIntent = new Intent(UserFragment.UPDATE_DESKTOP_ICON_ACTION); + intent.setPackage(BuildConfig.APPLICATION_ID); + context.sendBroadcast(updateIntent); + + switch (action) { + case Intent.ACTION_PACKAGE_ADDED: + case Intent.ACTION_PACKAGE_REPLACED: + case Intent.ACTION_PACKAGE_CHANGED: + if (JxwPackageConfig.JXW_LAUNCHER_PACKAGE_NAME.equals(packageName)) { + //刚刚安装完打开会失败 + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + ActivationUtil.getInstance().startJxwLauncher(); + } + }, 2345); + } + break; + case Intent.ACTION_PACKAGE_REMOVED: + if (JxwPackageConfig.JXW_LAUNCHER_PACKAGE_NAME.equals(packageName)) { + mMMKV.encode(MainService.JXW_REGISTER_SUCCESS, false); + } + break; + default: + break; + } + + + } + +} diff --git a/app/src/main/java/com/xwad/os/service/DownloadService.java b/app/src/main/java/com/xwad/os/service/DownloadService.java index 2382dbf..5e152ba 100644 --- a/app/src/main/java/com/xwad/os/service/DownloadService.java +++ b/app/src/main/java/com/xwad/os/service/DownloadService.java @@ -49,6 +49,7 @@ public class DownloadService extends Service { mNotificationManagerCompat = NotificationManagerCompat.from(this); createNotificationChannel(); createDownloadNotificationChannel(); + sendSimpleNotification(); } @Override @@ -92,7 +93,7 @@ public class DownloadService extends Service { PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID) .setSmallIcon(R.mipmap.ic_launcher) - .setContentTitle("关怀系统正在运行") + .setContentTitle("学王365正在运行") // .setContentText("测试内容") .setAutoCancel(false) .setShowWhen(false) @@ -131,8 +132,8 @@ public class DownloadService extends Service { .setProgress(100, progress, false) .setPriority(NotificationCompat.PRIORITY_HIGH); // notificationId is a unique int for each notification that you must define -// mNotificationManagerCompat.notify(ariaDownloadInfo.getAppId(), builder.build()); - startForeground(ariaDownloadInfo.getAppId(), builder.build()); + mNotificationManagerCompat.notify(ariaDownloadInfo.getAppId(), builder.build()); +// startForeground(ariaDownloadInfo.getAppId(), builder.build()); } private void sendDownloadComplete(AriaDownloadInfo ariaDownloadInfo, String path) { diff --git a/app/src/main/java/com/xwad/os/service/SocketService.java b/app/src/main/java/com/xwad/os/service/SocketService.java index 7641212..da0d70c 100644 --- a/app/src/main/java/com/xwad/os/service/SocketService.java +++ b/app/src/main/java/com/xwad/os/service/SocketService.java @@ -1,34 +1,34 @@ package com.xwad.os.service; -import android.app.NotificationChannel; -import android.app.NotificationManager; -import android.app.PendingIntent; import android.app.Service; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Binder; -import android.os.Build; import android.os.IBinder; import android.text.TextUtils; import android.util.Log; import androidx.annotation.Nullable; -import androidx.core.app.NotificationCompat; -import androidx.core.app.NotificationManagerCompat; +import com.alibaba.sdk.android.push.CloudPushService; +import com.alibaba.sdk.android.push.CommonCallback; +import com.alibaba.sdk.android.push.noonesdk.PushServiceFactory; import com.blankj.utilcode.util.NetworkUtils; +import com.google.gson.JsonElement; import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.hjq.toast.Toaster; import com.tencent.mmkv.MMKV; import com.xwad.os.BuildConfig; -import com.xwad.os.R; -import com.xwad.os.activity.main.MainActivity; +import com.xwad.os.activity.login.LoginActivity; import com.xwad.os.config.CommonConfig; +import com.xwad.os.gson.GsonUtils; import com.xwad.os.manager.DeviceSNManager; -import com.xwad.os.manager.RemoteManager; +import com.xwad.os.network.NetInterfaceManager; +import com.xwad.os.network.UrlAddress; import com.xwad.os.utils.ActivationUtil; -import com.xwad.os.utils.LenovoCsdkUtil; import com.xwad.os.utils.Utils; import com.xwad.os.websocket.JWebSocketClient; @@ -62,7 +62,10 @@ public class SocketService extends Service implements NetworkUtils.OnNetworkStat private MMKV mMMKV = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE); - public JWebSocketClient mJWebSocketClient; + private CloudPushService mCloudPushService; + + public JWebSocketClient mOnlineJWebSocketClient; + public JWebSocketClient mSsoJWebSocketClient; // private SocketServiceBinder mBinder = new SocketServiceBinder(); @Override @@ -116,16 +119,18 @@ public class SocketService extends Service implements NetworkUtils.OnNetworkStat NetworkUtils.registerNetworkStatusChangedListener(this); registerScreenLockReceiver(); - registerJxwRegisterRefreshReceiver(); + mCloudPushService = PushServiceFactory.getCloudPushService(); if (ActivationUtil.getInstance().isLogin()) { //初始化websocket - initSocketClient(); - startLoop(); + initOnlineSocketClient(); + initSsoSocketClient(); + initPush(); } else { Log.e(TAG, "onCreate: 未激活不连接"); } + // boolean isServiceRunning = ServiceAliveUtils.isServiceAlive(this, MainService.class.getName()); // Log.e(TAG, "onCreate: isServiceRunning = " + isServiceRunning); // if (!isServiceRunning) { @@ -133,15 +138,26 @@ public class SocketService extends Service implements NetworkUtils.OnNetworkStat // } // bindService(new Intent(this, ManagerService.class), mServiceConnection, Context.BIND_IMPORTANT); - mNotificationManagerCompat = NotificationManagerCompat.from(this); - createNotificationChannel(); -// showNotification(); - sendSimpleNotification(); } + public static final String LOGIN_SUCCESSFUL = "login_successful"; + @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.e(TAG, "onStartCommand: "); + if (intent != null) { + String action = intent.getAction(); + if (!TextUtils.isEmpty(action)) { + Log.e(TAG, "onStartCommand: action = " + action); + switch (action) { + case LOGIN_SUCCESSFUL: + initOnlineSocketClient(); + initSsoSocketClient(); + initPush(); + break; + } + } + } return START_STICKY; } @@ -150,56 +166,75 @@ public class SocketService extends Service implements NetworkUtils.OnNetworkStat super.onDestroy(); NetworkUtils.unregisterNetworkStatusChangedListener(this); dispose(); - closeConnect(); + closeOnlineConnect(); + closeSsoConnect(); if (mScreenLockReceiver != null) { unregisterReceiver(mScreenLockReceiver); } - if (mJxwRegisterReceiver != null) { - unregisterReceiver(mJxwRegisterReceiver); - } // unbindService(mServiceConnection); } - private static final String CHANNEL_ID = "CHANNEL_ID"; - private static final String CHANNEL_NAME = "系统通知"; - private static final String CHANNEL_DESCRIPTION = "学习课堂通知"; - - private void createNotificationChannel() { - // Create the NotificationChannel, but only on API 26+ because - // the NotificationChannel class is new and not in the support library - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - CharSequence name = CHANNEL_NAME; - String description = CHANNEL_DESCRIPTION; - int importance = NotificationManager.IMPORTANCE_DEFAULT; - NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance); - channel.setDescription(description); - // Register the channel with the system; you can't change the importance - // or other notification behaviors after this - NotificationManager notificationManager = getSystemService(NotificationManager.class); - notificationManager.createNotificationChannel(channel); + private void dispose() { + if (mOnlineDisposable != null && !mOnlineDisposable.isDisposed()) { + mOnlineDisposable.dispose(); + mOnlineDisposable = null; + } + if (mSsoDisposable != null && !mSsoDisposable.isDisposed()) { + mSsoDisposable.dispose(); + mSsoDisposable = null; } } - private NotificationManagerCompat mNotificationManagerCompat; - private int NotificationID = 1; + public void initPush() { + mCloudPushService.register(this, new CommonCallback() { + @Override + public void onSuccess(String response) { + Log.e("AliyunPush", "init cloudchannel success"); + Log.e("AliyunPush", "init cloudchannel success " + mCloudPushService.getDeviceId()); +// mMMKV.encode(CommonConfig.ALIYUN_PUSH_ID, mCloudPushService.getDeviceId()); + bindSn(); + } - private void sendSimpleNotification() { - Intent intent = new Intent(this, MainActivity.class); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); - PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); - NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "CHANNEL_ID") - .setSmallIcon(R.mipmap.ic_launcher) - .setContentTitle("学习课堂正在运行") -// .setContentText("测试内容") - .setAutoCancel(false) - .setShowWhen(false) - .setContentIntent(pendingIntent) - .setOngoing(true) - .setOnlyAlertOnce(true) - .setPriority(NotificationCompat.PRIORITY_MAX); - // notificationId is a unique int for each notification that you must define -// mNotificationManagerCompat.notify(NotificationID, builder.build()); - startForeground(NotificationID, builder.build()); + @Override + public void onFailed(String errorCode, String errorMessage) { + Log.e("AliyunPush", "init cloudchannel failed -- errorcode:" + errorCode + " -- errorMessage:" + errorMessage); +// mMMKV.encode(CommonConfig.ALIYUN_PUSH_ID, errorCode + errorMessage); + if ("PUSH_20110".equals(errorCode)) { + bindSn(); + } + } + }); + } + + private void bindSn() { + String sn = DeviceSNManager.getDeviceSN(); + if (TextUtils.isEmpty(sn)) { + return; + } + mCloudPushService.bindAccount(sn, new CommonCallback() { + @Override + public void onSuccess(String s) { + Log.e("AliyunPush", "bind account " + sn + " success\n"); + } + + @Override + public void onFailed(String errorCode, String errorMsg) { + Log.e("AliyunPush", "bind account " + sn + " failed." + + "errorCode: " + errorCode + ", errorMsg:" + errorMsg); + } + }); + mCloudPushService.addAlias(sn, new CommonCallback() { + @Override + public void onSuccess(String s) { + Log.e("AliyunPush", "add alias " + sn + " success\n"); + } + + @Override + public void onFailed(String errorCode, String errorMsg) { + Log.e("AliyunPush", "add alias " + sn + " failed." + + "errorCode: " + errorCode + ", errorMsg:" + errorMsg + "\n"); + } + }); } private ScreenLockReceiver mScreenLockReceiver; @@ -234,13 +269,13 @@ public class SocketService extends Service implements NetworkUtils.OnNetworkStat case Intent.ACTION_USER_PRESENT: case Intent.ACTION_SCREEN_ON: - sendMsgScreen(); + sendOnlineMsgScreen(); break; case Intent.ACTION_SCREEN_OFF: case Intent.ACTION_SHUTDOWN: case Intent.ACTION_FACTORY_RESET: case Intent.ACTION_MASTER_CLEAR: - sendMsgScreen(); + sendOnlineMsgScreen(); break; default: break; @@ -248,72 +283,38 @@ public class SocketService extends Service implements NetworkUtils.OnNetworkStat } } - public static final String JXW_REGISTER_SUCCESS = "com.zzj.regist_success"; + private Disposable mOnlineDisposable; - private JxwRegisterReceiver mJxwRegisterReceiver; - - private void registerJxwRegisterRefreshReceiver() { - if (mJxwRegisterReceiver == null) { - mJxwRegisterReceiver = new JxwRegisterReceiver(); + private void startOnlineLoop() { + if (mOnlineDisposable != null && !mOnlineDisposable.isDisposed()) { + mOnlineDisposable.dispose(); + mOnlineDisposable = null; } - IntentFilter filter = new IntentFilter(); - filter.addAction(JXW_REGISTER_SUCCESS); - registerReceiver(mJxwRegisterReceiver, filter); - } - - public class JxwRegisterReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - Log.e("JxwRegisterReceiver", "onReceive: " + action); - if (JXW_REGISTER_SUCCESS.equals(action)) { - mMMKV.encode(JXW_REGISTER_SUCCESS, true); - mMMKV.encode(CommonConfig.UIUI_ACTIVATION_KEY, ActivationUtil.getInstance().ACTIVATED_KEY); - initSocketClient(); - startLoop(); - } - } - } - - private Disposable mDisposable; - - private void dispose() { - if (mDisposable != null && !mDisposable.isDisposed()) { - mDisposable.dispose(); - mDisposable = null; - } - } - - private void startLoop() { - if (mDisposable != null && !mDisposable.isDisposed()) { - mDisposable.dispose(); - mDisposable = null; - } - mDisposable = Observable.interval(30, TimeUnit.SECONDS) + mOnlineDisposable = Observable.interval(30, TimeUnit.SECONDS) .subscribe(new Consumer() { @Override public void accept(Long s) throws Exception { - Log.d(TAG, "startLoop accept: " + s); + Log.d(TAG, "startOnlineLoop accept: " + s); Log.i(TAG, "心跳包检测websocket连接状态"); if (!ActivationUtil.getInstance().isLogin()) { dispose(); } //每隔一定的时间,对长连接进行一次心跳检测 if (Utils.isScreenOn(SocketService.this)) { - if (mJWebSocketClient != null) { - if (mJWebSocketClient.isOpen()) { - Log.i(TAG, "websocket已连接"); - sendPingMsg(); - } else if (mJWebSocketClient.isClosed()) { - Log.i(TAG, "websocket重连中"); - reconnectWs(); + if (mOnlineJWebSocketClient != null) { + if (mOnlineJWebSocketClient.isOpen()) { + Log.i(TAG, "startOnlineLoop websocket已连接"); + sendOnlinePingMsg(); + } else if (mOnlineJWebSocketClient.isClosed()) { + Log.i(TAG, "startOnlineLoop websocket重连中"); + reconnectOnlineWs(); } } else { //如果client已为空,重新初始化连接 - initSocketClient(); + initOnlineSocketClient(); } } else { - Log.i(TAG, "websocket息屏不重连"); + Log.i(TAG, "startOnlineLoop websocket息屏不重连"); } } }); @@ -322,59 +323,60 @@ public class SocketService extends Service implements NetworkUtils.OnNetworkStat /** * 初始化websocket连接 */ - private void initSocketClient() { - URI uri = URI.create(BuildConfig.WEBSOCKET_URL + "?sn=" + DeviceSNManager.getDeviceSN()); - mJWebSocketClient = new JWebSocketClient(uri) { + private void initOnlineSocketClient() { + URI uri = URI.create(UrlAddress.WEBSOCKET_URL_ONLINE + "?sn=" + DeviceSNManager.getDeviceSN()); + mOnlineJWebSocketClient = new JWebSocketClient(uri) { @Override public void onMessage(String message) { - Log.i(TAG, "onMessage: 收到服务器发来的消息:" + message); + Log.i(TAG, "Online onMessage: 收到服务器发来的消息:" + message); } @Override public void onOpen(ServerHandshake handshakedata) { super.onOpen(handshakedata); - Log.i(TAG, "onOpen: websocket连接成功"); - sendPingMsg(); + Log.i(TAG, "Online onOpen: websocket连接成功"); + sendOnlinePingMsg(); } @Override public void onClose(int code, String reason, boolean remote) { super.onClose(code, reason, remote); - Log.e(TAG, "onClose: websocket连接关闭:" + reason); - mJWebSocketClient = null; + Log.e(TAG, "Online onClose: websocket连接关闭:" + reason); + mOnlineJWebSocketClient = null; } @Override public void onError(Exception ex) { super.onError(ex); - Log.e(TAG, "onError: websocket连接错误:" + ex.getMessage()); - mJWebSocketClient = null; + Log.e(TAG, "Online onError: websocket连接错误:" + ex.getMessage()); + mOnlineJWebSocketClient = null; } }; - connect(); + connectOnlineWs(); + startOnlineLoop(); } /** * 连接websocket */ - private void connect() { + private void connectOnlineWs() { try { //connectBlocking多出一个等待操作,会先连接再发送,否则未连接发送会报错 - Log.i(TAG, "connect: websocket连接中"); - mJWebSocketClient.connectBlocking(); + Log.i(TAG, "connectOnlineWs: websocket连接中"); + mOnlineJWebSocketClient.connectBlocking(); } catch (Exception e) { - Log.i(TAG, "connect: " + e.getMessage()); + Log.i(TAG, "connectOnlineWs: " + e.getMessage()); } } /** * 开启重连 */ - private void reconnectWs() { - Log.e(TAG, "reconnectWs: "); + private void reconnectOnlineWs() { + Log.e(TAG, "reconnectOnlineWs: "); try { - Log.i(TAG, "reconnectWs: 开启重连"); - mJWebSocketClient.reconnectBlocking(); + Log.i(TAG, "reconnectOnlineWs: 开启重连"); + mOnlineJWebSocketClient.reconnectBlocking(); } catch (InterruptedException e) { e.printStackTrace(); } @@ -383,33 +385,33 @@ public class SocketService extends Service implements NetworkUtils.OnNetworkStat /** * 断开连接 */ - private void closeConnect() { - Log.e(TAG, "closeConnect: "); + private void closeOnlineConnect() { + Log.e(TAG, "closeOnlineConnect: "); try { - if (null != mJWebSocketClient) { - mJWebSocketClient.close(); + if (null != mOnlineJWebSocketClient) { + mOnlineJWebSocketClient.close(); } } catch (Exception e) { e.printStackTrace(); } finally { - mJWebSocketClient = null; + mOnlineJWebSocketClient = null; } } /** * 发送消息 */ - public void sendPingMsg() { + public void sendOnlinePingMsg() { JsonObject jsonObject = new JsonObject(); jsonObject.addProperty("sn", DeviceSNManager.getDeviceSN()); jsonObject.addProperty("type", "ping"); - if (null != mJWebSocketClient) { - Log.i(TAG, "sendPingMsg: 发送的消息:" + jsonObject.toString()); - mJWebSocketClient.send(jsonObject.toString()); + if (null != mOnlineJWebSocketClient) { + Log.i(TAG, "sendOnlinePingMsg: 发送的消息:" + jsonObject.toString()); + mOnlineJWebSocketClient.send(jsonObject.toString()); } } - public void sendMsgScreen() { + public void sendOnlineMsgScreen() { JsonObject jsonObject = new JsonObject(); jsonObject.addProperty("sn", DeviceSNManager.getDeviceSN()); if (Utils.isScreenOn(SocketService.this)) { @@ -418,18 +420,170 @@ public class SocketService extends Service implements NetworkUtils.OnNetworkStat jsonObject.addProperty("type", "device_close_screen"); //熄屏状态 } - if (null != mJWebSocketClient) { - Log.i(TAG, "sendMsgScreen: 发送的消息" + jsonObject.toString()); + if (null != mOnlineJWebSocketClient) { + Log.i(TAG, "sendOnlineMsgScreen: 发送的消息" + jsonObject.toString()); try { - mJWebSocketClient.send(jsonObject.toString()); + mOnlineJWebSocketClient.send(jsonObject.toString()); } catch (Exception e) { - Log.i(TAG, "sendMsgScreen: sendMsg Exception: " + e.getLocalizedMessage()); + Log.i(TAG, "sendOnlineMsgScreen: sendMsg Exception: " + e.getLocalizedMessage()); } } else { - Log.i(TAG, "sendMsgScreen: 未连接"); - initSocketClient(); + Log.i(TAG, "sendOnlineMsgScreen: 未连接"); + initOnlineSocketClient(); } } + private Disposable mSsoDisposable; + + private void startSsoLoop() { + if (mSsoDisposable != null && !mSsoDisposable.isDisposed()) { + mSsoDisposable.dispose(); + mSsoDisposable = null; + } + mSsoDisposable = Observable.interval(30, TimeUnit.SECONDS) + .subscribe(new Consumer() { + @Override + public void accept(Long s) throws Exception { + Log.d(TAG, "startSsoLoop accept: " + s); + Log.i(TAG, "startSsoLoop 心跳包检测websocket连接状态"); + if (!ActivationUtil.getInstance().isLogin()) { + dispose(); + } + //每隔一定的时间,对长连接进行一次心跳检测 + if (Utils.isScreenOn(SocketService.this)) { + if (mSsoJWebSocketClient != null) { + if (mSsoJWebSocketClient.isOpen()) { + Log.i(TAG, "startSsoLoop websocket已连接"); + sendSsoPingMsg(); + } else if (mSsoJWebSocketClient.isClosed()) { + Log.i(TAG, "startSsoLoop websocket重连中"); + reconnectSsoWs(); + } + } else { + //如果client已为空,重新初始化连接 + initSsoSocketClient(); + } + } else { + Log.i(TAG, "startSsoLoop websocket息屏不重连"); + } + } + }); + } + + /** + * 初始化websocket连接 + */ + private void initSsoSocketClient() { + URI uri = URI.create(UrlAddress.WEBSOCKET_URL_SSO + "?sn=" + DeviceSNManager.getDeviceSN() + "&token=" + NetInterfaceManager.getInstance().getToken()); + mSsoJWebSocketClient = new JWebSocketClient(uri) { + @Override + public void onMessage(String message) { + if (BuildConfig.DEBUG) { + Log.i(TAG, "sso onMessage: 收到服务器发来的消息:" + message); + } + checkOffLine(message); + } + + @Override + public void onOpen(ServerHandshake handshakedata) { + super.onOpen(handshakedata); + Log.i(TAG, "sso onOpen: websocket连接成功"); + sendSsoPingMsg(); + } + + @Override + public void onClose(int code, String reason, boolean remote) { + super.onClose(code, reason, remote); + Log.e(TAG, "sso onClose: websocket连接关闭:" + reason); + mSsoJWebSocketClient = null; + } + + @Override + public void onError(Exception ex) { + super.onError(ex); + Log.e(TAG, "sso onError: websocket连接错误:" + ex.getMessage()); + mSsoJWebSocketClient = null; + } + }; + connectSsoWs(); + startSsoLoop(); + } + + /** + * 连接websocket + */ + private void connectSsoWs() { + try { + //connectBlocking多出一个等待操作,会先连接再发送,否则未连接发送会报错 + Log.i(TAG, "connectSsoWs: websocket连接中"); + mSsoJWebSocketClient.connectBlocking(); + } catch (Exception e) { + Log.i(TAG, "connectSsoWs: " + e.getMessage()); + } + } + + /** + * 开启重连 + */ + private void reconnectSsoWs() { + Log.e(TAG, "reconnectSsoWs: "); + try { + Log.i(TAG, "reconnectSsoWs: 开启重连"); + mSsoJWebSocketClient.reconnectBlocking(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + /** + * 断开连接 + */ + private void closeSsoConnect() { + Log.e(TAG, "closeSsoConnect: "); + try { + if (null != mSsoJWebSocketClient) { + mSsoJWebSocketClient.close(); + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + mSsoJWebSocketClient = null; + } + } + + /** + * 发送消息 + */ + public void sendSsoPingMsg() { + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("type", "ping"); + jsonObject.addProperty("sn", DeviceSNManager.getDeviceSN()); + jsonObject.addProperty("token", NetInterfaceManager.getInstance().getToken()); + if (null != mSsoJWebSocketClient) { + Log.i(TAG, "sendPingMsg: 发送的消息:" + jsonObject.toString()); + mSsoJWebSocketClient.send(jsonObject.toString()); + } + } + + private void checkOffLine(String jsonString) { + if (TextUtils.isEmpty(jsonString)) return; + JsonObject jsonObject = GsonUtils.getJsonObject(jsonString); + JsonElement jsonElement = jsonObject.get("type"); + if (jsonElement != null) { + String type = jsonElement.getAsString(); + if ("kick_out".equals(type)) { + ActivationUtil.getInstance().setActivation(0); + mMMKV.encode(CommonConfig.ACCOUNT_LOGIN_STATU, 0); + mMMKV.encode(CommonConfig.ACCOUNT_LOGIN_TOKEN, ""); + Toaster.showLong("请重新登录"); + Intent intent = new Intent(SocketService.this, LoginActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); +// intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); + startActivity(intent); + dispose(); + } + } + } + } diff --git a/app/src/main/java/com/xwad/os/service/main/MainService.java b/app/src/main/java/com/xwad/os/service/main/MainService.java index e212ee0..f723398 100644 --- a/app/src/main/java/com/xwad/os/service/main/MainService.java +++ b/app/src/main/java/com/xwad/os/service/main/MainService.java @@ -1,20 +1,30 @@ package com.xwad.os.service.main; +import android.app.NotificationChannel; +import android.app.NotificationManager; +import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.os.Build; import android.os.IBinder; import android.text.TextUtils; import android.util.Log; +import androidx.core.app.NotificationCompat; +import androidx.core.app.NotificationManagerCompat; + import com.blankj.utilcode.util.NetworkUtils; import com.tencent.mmkv.MMKV; +import com.xwad.os.R; import com.xwad.os.activity.NoticeActivity; +import com.xwad.os.activity.main.MainActivity; import com.xwad.os.alarm.AlarmUtils; import com.xwad.os.base.rx.BaseRxService; import com.xwad.os.bean.AlarmClockData; import com.xwad.os.config.CommonConfig; +import com.xwad.os.service.SocketService; import java.util.Calendar; import java.util.HashMap; @@ -60,6 +70,13 @@ public class MainService extends BaseRxService implements MainSContact.MainSView registerReceivers(); NetworkUtils.registerNetworkStatusChangedListener(this); startJxwLauncher(); + + mNotificationManagerCompat = NotificationManagerCompat.from(this); + createNotificationChannel(); +// showNotification(); + sendSimpleNotification(); + + startService(new Intent(MainService.this, SocketService.class)); } @Override @@ -76,6 +93,45 @@ public class MainService extends BaseRxService implements MainSContact.MainSView unregisterReceiver(); } + private static final String CHANNEL_ID = "CHANNEL_ID"; + private static final String CHANNEL_NAME = "系统通知"; + private static final String CHANNEL_DESCRIPTION = "学王365通知"; + + private void createNotificationChannel() { + // Create the NotificationChannel, but only on API 26+ because + // the NotificationChannel class is new and not in the support library + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT); + channel.setDescription(CHANNEL_DESCRIPTION); + // Register the channel with the system; you can't change the importance + // or other notification behaviors after this + NotificationManager notificationManager = getSystemService(NotificationManager.class); + notificationManager.createNotificationChannel(channel); + } + } + + private NotificationManagerCompat mNotificationManagerCompat; + private int NotificationID = 1; + + private void sendSimpleNotification() { + Intent intent = new Intent(this, MainActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); + PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); + NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID) + .setSmallIcon(R.mipmap.ic_launcher) + .setContentTitle("学王365正在运行") +// .setContentText("测试内容") + .setAutoCancel(false) + .setShowWhen(false) + .setContentIntent(pendingIntent) + .setOngoing(true) + .setOnlyAlertOnce(true) + .setPriority(NotificationCompat.PRIORITY_MAX); + // notificationId is a unique int for each notification that you must define +// mNotificationManagerCompat.notify(NotificationID, builder.build()); + startForeground(NotificationID, builder.build()); + } + private void startJxwLauncher() { // ComponentName cn = new ComponentName(JxwPackageConfig.JXW_LAUNCHER_PACKAGE_NAME, JxwPackageConfig.JXW_LAUNCHER_CLASS_NAME); // Intent intent = new Intent(); diff --git a/app/src/main/java/com/xwad/os/utils/ActivationUtil.java b/app/src/main/java/com/xwad/os/utils/ActivationUtil.java index 9f90fa3..5ec7a6e 100644 --- a/app/src/main/java/com/xwad/os/utils/ActivationUtil.java +++ b/app/src/main/java/com/xwad/os/utils/ActivationUtil.java @@ -8,6 +8,7 @@ import android.util.Log; import com.tencent.mmkv.MMKV; import com.xwad.os.config.CommonConfig; +import com.xwad.os.jxw.JxwPackageConfig; import com.xwad.os.service.main.MainService; public class ActivationUtil { @@ -112,18 +113,23 @@ public class ActivationUtil { return mMMKV.decodeLong(CommonConfig.UIUI_EXPIRE_TIME_KEY, DEFAULT_EXPIRE_TIME); } + public String getActivationCode() { + return mMMKV.decodeString(CommonConfig.ACTIVATIONBEAN_CODE_KEY, ""); + } + public boolean isLogin() { return mMMKV.decodeInt(CommonConfig.ACCOUNT_LOGIN_STATU, 0) == 1; } public void startJxwLauncher() { - String code = mMMKV.decodeString(CommonConfig.ACTIVATIONBEAN_CODE_KEY, ""); + String code = getActivationCode(); boolean regist_success = mMMKV.decodeBool(MainService.JXW_REGISTER_SUCCESS, false); if (!regist_success) { Intent intent = new Intent("UIUI_ACTIVATION"); - ComponentName componentName = new ComponentName("com.jxw.launcher", "com.jxw.engine.platsign.MainActivity"); + ComponentName componentName = new ComponentName(JxwPackageConfig.JXW_LAUNCHER_PACKAGE_NAME, JxwPackageConfig.JXW_LAUNCHER_DUMMY_ACTIVITY); intent.setComponent(componentName); - intent.putExtra("uiui_activation_code", code); +// intent.putExtra("uiui_activation_code", code); + intent.putExtra("series", code); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); try { mContext.startActivity(intent); diff --git a/app/src/main/java/com/xwad/os/utils/JxwUtils.java b/app/src/main/java/com/xwad/os/utils/JxwUtils.java new file mode 100644 index 0000000..20eea57 --- /dev/null +++ b/app/src/main/java/com/xwad/os/utils/JxwUtils.java @@ -0,0 +1,87 @@ +package com.xwad.os.utils; + +import android.util.Log; + +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.HashMap; +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; + +public class JxwUtils { + private static final String TAG = "JxwUtils"; + + static { + System.loadLibrary("xuewang"); // 加载 libjniutils.so + } + + // 声明为Native方法 + public static native String getAppId(); + + public static native String getAppSecret(); + + public static String getSignature(Map paramMap) { + long timeStamp = System.currentTimeMillis(); + //用于获取signature + SortedMap items = new TreeMap<>(); + items.put("nonce", "X6SH3YeRTs"); + items.put("appId", JxwUtils.getAppId()); + items.put("appsecret", JxwUtils.getAppSecret()); + items.put("timestamp", String.valueOf(timeStamp)); +// items.putAll(paramMap); + +// items.put("其它参数", "其它参数的值"); + String signature = signature(items); + Log.e(TAG, "userScore: " + signature); + + +// //请求参数设置 +// Map paramMap = new HashMap<>(); +// paramMap.put("nonce", "X6SH3YeRTs"); +// paramMap.put("appId", JxwUtils.getAppId()); +// paramMap.put("signature", signature); +// paramMap.put("timestamp", String.valueOf(timeStamp)); +//// paramMap.put("其它参数", "其它参数的值"); + + return signature; + } + + public static String signature(SortedMap items) { + StringBuilder forSign = new StringBuilder(); + + for (String key : items.keySet()) { + forSign.append(key).append("=").append(items.get(key)).append("&"); + } + + forSign.setLength(forSign.length() - 1); + + return encryptSHA1(forSign.toString()); + } + + public static String encryptSHA1(String content) { + try { + MessageDigest digest = MessageDigest.getInstance("SHA-1"); + digest.update(content.getBytes(StandardCharsets.UTF_8)); + byte[] messageDigest = digest.digest(); + StringBuilder hexString = new StringBuilder(); + + for (byte b : messageDigest) { + String shaHex = Integer.toHexString(b & 0xFF); + + if (shaHex.length() < 2) { + hexString.append(0); + } + + hexString.append(shaHex); + } + + return hexString.toString(); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } + return null; + } + +} diff --git a/app/src/main/java/com/xwad/os/utils/OpenApkUtils.java b/app/src/main/java/com/xwad/os/utils/OpenApkUtils.java index e62dbb4..cf16262 100644 --- a/app/src/main/java/com/xwad/os/utils/OpenApkUtils.java +++ b/app/src/main/java/com/xwad/os/utils/OpenApkUtils.java @@ -15,7 +15,6 @@ import android.util.Log; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; -import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager; import android.widget.TextView; @@ -24,7 +23,10 @@ import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import com.hjq.toast.Toaster; import com.tencent.mmkv.MMKV; +import com.xwad.os.BuildConfig; import com.xwad.os.R; +import com.xwad.os.activity.activation.ActivationActivity; +import com.xwad.os.activity.login.LoginActivity; import com.xwad.os.bean.AppInfo; import com.xwad.os.bean.BaseResponse; import com.xwad.os.bean.LessonJson; @@ -34,6 +36,7 @@ import com.xwad.os.jxw.SPUtils; import com.xwad.os.manager.RemoteManager; import com.xwad.os.network.NetInterfaceManager; import com.xwad.os.service.DownloadService; +import com.xwad.os.view.jxw.widget.DefaultAppsDialog; import java.lang.reflect.Type; import java.math.BigDecimal; @@ -658,17 +661,44 @@ public class OpenApkUtils { return false; } + public void openJxwAppWithParam(Activity activity, String paramStr, boolean checkInstall) { + if (checkInstall) { + if (!ApkUtils.isAvailable(activity, "com.jxw.launcher") || !ApkUtils.isAvailable(activity, "com.jxw.download")) { + DefaultAppsDialog appsDialog = new DefaultAppsDialog(activity); + appsDialog.show(); + Toaster.show("请先安装必备组件"); + return; + } + } + +// if (!BuildConfig.DEBUG){ + if (!ActivationUtil.getInstance().isLogin()) { + Toaster.show("请先登录"); + activity.startActivity(new Intent(activity, LoginActivity.class)); + return; + } + + if (!ActivationUtil.getInstance().isActivation()) { + Toaster.show("请先激活后使用"); + activity.startActivity(new Intent(activity, ActivationActivity.class)); + return; + } + + if (TextUtils.isEmpty(paramStr)) { + Log.e(TAG, "context为空或参数字符串为空"); + return; + } +// } + + openJxwApp(activity, paramStr); + } + /** * 根据参数字符串打开对应页面 * * @param paramStr 参数字符串(格式:包名,类名,extra参数,第四项,第五项) */ public void openJxwApp(Activity activity, String paramStr) { - if (TextUtils.isEmpty(paramStr)) { - Log.e(TAG, "context为空或参数字符串为空"); - return; - } - // 1. 按逗号分割整体参数(保留空项,避免丢失字段) String[] totalParts = paramStr.split(",", -1); if (totalParts.length < 2) { // 至少需要包名+类名 @@ -877,6 +907,7 @@ public class OpenApkUtils { this.add("com.hihonor.deskclock"); this.add("com.huawei.deskclock"); this.add("com.coloros.alarmclock"); + this.add("com.zui.deskclock"); this.add("com.android.BBKClock"); }}; @@ -896,6 +927,7 @@ public class OpenApkUtils { this.add("com.huawei.calculator"); this.add("com.miui.calculator"); this.add("com.coloros.calculator"); + this.add("com.zui.calculator"); this.add("com.android.bbkcalculator"); }}; @@ -911,9 +943,13 @@ public class OpenApkUtils { public String getCameraPackageName() { List pkgList = new ArrayList() {{ this.add("com.android.camera"); + this.add("com.android.camera2"); + this.add("com.mediatek.camera"); + this.add("com.softwinner.camera"); this.add("com.hihonor.camera"); this.add("com.huawei.camera"); this.add("com.oplus.camera"); + this.add("com.zui.camera"); }}; Optional optional = pkgList.stream().filter(new Predicate() { @@ -933,6 +969,7 @@ public class OpenApkUtils { this.add("com.miui.gallery"); this.add("com.coloros.gallery3d"); this.add("com.vivo.gallery"); + this.add("com.zui.gallery"); }}; Optional optional = pkgList.stream().filter(new Predicate() { diff --git a/app/src/main/java/com/xwad/os/view/jxw/widget/AppsDialog.java b/app/src/main/java/com/xwad/os/view/jxw/widget/AppsDialog.java index 1587c0c..8f3babc 100644 --- a/app/src/main/java/com/xwad/os/view/jxw/widget/AppsDialog.java +++ b/app/src/main/java/com/xwad/os/view/jxw/widget/AppsDialog.java @@ -188,7 +188,7 @@ public class AppsDialog extends Dialog { } // MyApp.getInstance().mBottomBtnOnClickListener.setContext(activity); // MyApp.getInstance().mBottomBtnOnClickListener.onClick(viewTag); - OpenApkUtils.getInstance().openJxwApp(activity, viewTag); + OpenApkUtils.getInstance().openJxwAppWithParam(activity, viewTag, true); } } diff --git a/app/src/main/java/com/xwad/os/view/jxw/widget/DefaultAppsDialog.java b/app/src/main/java/com/xwad/os/view/jxw/widget/DefaultAppsDialog.java index 906788d..a0fb27a 100644 --- a/app/src/main/java/com/xwad/os/view/jxw/widget/DefaultAppsDialog.java +++ b/app/src/main/java/com/xwad/os/view/jxw/widget/DefaultAppsDialog.java @@ -6,13 +6,14 @@ import android.content.Context; import android.graphics.Point; import android.os.Bundle; import android.text.TextUtils; +import android.util.Log; import android.view.Display; import android.view.View; import android.view.WindowManager; import android.widget.ImageView; -import android.widget.RelativeLayout; import android.widget.TextView; +import androidx.constraintlayout.widget.ConstraintLayout; import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.RecyclerView; @@ -20,12 +21,15 @@ import com.chad.library.adapter.base.BaseQuickAdapter; import com.chad.library.adapter.base.BaseViewHolder; import com.xwad.os.R; import com.xwad.os.bean.jxw.ItemsBean; +import com.xwad.os.utils.ApkUtils; import com.xwad.os.utils.OpenApkUtils; import java.util.ArrayList; import java.util.List; public class DefaultAppsDialog extends Dialog { + private static final String TAG = "DefaultAppsDialog"; + private Activity activity; private AppAdapter appAdapter; @@ -61,7 +65,7 @@ public class DefaultAppsDialog extends Dialog { } private void initView() { - GridLayoutManager gridLayoutManager = new GridLayoutManager(activity, 2); + GridLayoutManager gridLayoutManager = new GridLayoutManager(activity, 3); rv_apps = findViewById(R.id.rv_apps); appAdapter = new AppAdapter(getDefaultApps()); rv_apps.setLayoutManager(gridLayoutManager); @@ -86,10 +90,19 @@ public class DefaultAppsDialog extends Dialog { @Override public void convert(BaseViewHolder baseViewHolder, final ItemsBean itemsBean) { - RelativeLayout relativeLayout = baseViewHolder.getView(R.id.rl_root); - ((ImageView) baseViewHolder.getView(R.id.iv_app_icon)).setImageResource(mContext.getResources().getIdentifier(itemsBean.getIcon(), "drawable", mContext.getPackageName())); - ((TextView) baseViewHolder.getView(R.id.tv_app_name)).setText(itemsBean.getText()); - relativeLayout.setOnClickListener(new View.OnClickListener() { + ConstraintLayout constraintLayout = baseViewHolder.getView(R.id.rl_root); + ImageView iv_download = baseViewHolder.getView(R.id.iv_download); + if (ApkUtils.isAvailable(mContext, getPackageName(itemsBean.getTag()))) { + iv_download.setVisibility(View.GONE); + } else { + iv_download.setVisibility(View.VISIBLE); + } + ImageView iv_app_icon = baseViewHolder.getView(R.id.iv_app_icon); + iv_app_icon.setImageResource(mContext.getResources().getIdentifier(itemsBean.getIcon(), "drawable", mContext.getPackageName())); + TextView tv_app_name = baseViewHolder.getView(R.id.tv_app_name); + tv_app_name.setText(itemsBean.getText()); + + constraintLayout.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { jumpTag(itemsBean); @@ -98,6 +111,15 @@ public class DefaultAppsDialog extends Dialog { } } + private String getPackageName(String tag) { + if (TextUtils.isEmpty(tag)) { + return ""; + } + String pkg = tag.substring(0, tag.indexOf(",")); + Log.e(TAG, "getPackageName: " + pkg); + return pkg; + } + public void jumpTag(ItemsBean itemsBean) { if (activity != null) { Callback callback = mCallback; @@ -106,14 +128,15 @@ public class DefaultAppsDialog extends Dialog { } // MyApp.getInstance().mBottomBtnOnClickListener.setContext(activity); // MyApp.getInstance().mBottomBtnOnClickListener.onClick(viewTag); - OpenApkUtils.getInstance().openJxwApp(activity, itemsBean.getTag()); + OpenApkUtils.getInstance().openJxwAppWithParam(activity, itemsBean.getTag(), false); } } private List getDefaultApps() { List itemsBeans = new ArrayList<>(); - itemsBeans.add(new ItemsBean("icon_bbx_launcher", "", "com.jxw.launcher,,,,资源下载", "资源下载")); - itemsBeans.add(new ItemsBean("icon_bbx_player", "", "com.study.flashplayer,,,,播放器", "播放器")); + itemsBeans.add(new ItemsBean("icon_bbx_launcher", "", "com.jxw.launcher,com.jxw.launcher.DummyActivity,,,许可证校验", "许可证校验")); + itemsBeans.add(new ItemsBean("icon_bbx_xzzx", "", "com.jxw.download,com.jxw.download.main.ui.HomeActivity,,,下载中心", "下载中心")); + itemsBeans.add(new ItemsBean("icon_bbx_player", "", "com.study.flashplayer,,,,Flash播放器", "Flash播放器")); return itemsBeans; } } \ No newline at end of file diff --git a/app/src/main/jni/xuewang.cpp b/app/src/main/jni/xuewang.cpp new file mode 100644 index 0000000..f5149e5 --- /dev/null +++ b/app/src/main/jni/xuewang.cpp @@ -0,0 +1,26 @@ +// +// Created by TT on 2025/12/29. +// + +#include +#include +#include +// 日志打印 +#include + +#define LOG_TAG "TAG_LOG" +#define LOGI(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) + +extern "C" +JNIEXPORT jstring JNICALL +Java_com_xwad_os_utils_JxwUtils_getAppId(JNIEnv *env, jclass thiz) { + std::string key = "hlhdpb"; + return env->NewStringUTF(key.c_str()); +} + +extern "C" +JNIEXPORT jstring JNICALL +Java_com_xwad_os_utils_JxwUtils_getAppSecret(JNIEnv *env, jclass thiz) { + std::string key = "WDNUnYMNL33lqlGIIZB"; + return env->NewStringUTF(key.c_str()); +} \ No newline at end of file diff --git a/app/src/main/res/drawable-nodpi/icon_jxw_aizndy.png b/app/src/main/res/drawable-nodpi/icon_jxw_aizndy.png new file mode 100644 index 0000000000000000000000000000000000000000..6f2c1541575e858b1b6dd76d9c48f67e3919675a GIT binary patch literal 40328 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ðp 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 + + diff --git a/app/src/main/res/layout/activity_home.xml b/app/src/main/res/layout/activity_home.xml index 3b6b3c2..aee66b2 100644 --- a/app/src/main/res/layout/activity_home.xml +++ b/app/src/main/res/layout/activity_home.xml @@ -146,7 +146,9 @@ @@ -194,19 +194,23 @@ app:layout_constraintStart_toEndOf="@+id/view2" app:layout_constraintTop_toTopOf="parent" /> - + - + diff --git a/app/src/main/res/layout/activity_login_successful.xml b/app/src/main/res/layout/activity_login_successful.xml index ca796bf..5ef8fd9 100644 --- a/app/src/main/res/layout/activity_login_successful.xml +++ b/app/src/main/res/layout/activity_login_successful.xml @@ -34,7 +34,8 @@ app:layout_constraintBottom_toTopOf="@+id/constraintLayout17" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toTopOf="parent" /> + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintVertical_bias="0.333" /> + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_dialog_login_statu.xml b/app/src/main/res/layout/fragment_dialog_login_statu.xml index a0f11cc..983ba21 100644 --- a/app/src/main/res/layout/fragment_dialog_login_statu.xml +++ b/app/src/main/res/layout/fragment_dialog_login_statu.xml @@ -50,6 +50,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" + android:layout_marginBottom="24dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintTop_toBottomOf="@+id/constraintLayout15"> @@ -78,6 +79,7 @@ + + + + @@ -60,6 +66,8 @@ android:layout_height="48dp" android:layout_marginStart="16dp" android:src="@drawable/default_avatar" + app:error="@{@drawable/default_avatar}" + app:imageUrl="@{userAvatarInfo.avatar}" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> @@ -98,9 +106,10 @@ android:layout_height="wrap_content" android:ellipsize="marquee" android:singleLine="true" - android:text="@string/default_nickname" + android:text="@{userAvatarInfo==null?@string/default_nickname:userAvatarInfo.sn_name}" android:textColor="@color/white" - android:textSize="9sp" /> + android:textSize="9sp" + tools:text="@string/default_nickname" /> + android:tag="@string/tag_args_new_arzd" + android:visibility="gone"> + + + + + + + + + + + + + android:tag="@string/tag_args_updae" + android:visibility="gone"> + android:tag="@string/tag_args_new_jzgk" + android:visibility="gone"> + android:tag="@string/tag_args_new_yjjs" + android:visibility="gone"> - @@ -8,17 +9,33 @@ android:id="@+id/iv_app_icon" android:layout_width="28dp" android:layout_height="28dp" - android:layout_centerHorizontal="true" /> + android:layout_marginTop="8dp" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + + - \ No newline at end of file + android:textSize="9sp" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/iv_app_icon" /> + \ No newline at end of file diff --git a/app/src/main/res/layout/item_tab.xml b/app/src/main/res/layout/item_tab.xml index 4504f96..6919f80 100644 --- a/app/src/main/res/layout/item_tab.xml +++ b/app/src/main/res/layout/item_tab.xml @@ -4,8 +4,8 @@ android:layout_width="wrap_content" android:layout_height="34dp" android:orientation="vertical" - android:paddingStart="9dp" - android:paddingRight="9dp"> + android:paddingStart="6dp" + android:paddingRight="6dp"> com.jxw.tbdd,com.jxw.yyhb.ui.activity.MainActivity,int:subject:1,jxwgb_6.0_tbdd,同步点读 com.jxw.question,com.jxw.question.module.ui.activity.ProgramEntryActivity,,jxwgb_6.0_tiku_xiaodu,题库 com.jxw.zjcc,com.jxw.zjcc.MainActivity,,jxwgb_6.0_xwzdtl,指尖查词 + com.jxw.launcher,com.jxw.launcher.DummyActivity,,,许可证 com.jxw.launcher,com.jxw.update.UpdateNewActivity,,,应用更新 com.jxw.launcher,com.jxw.launcher.XtazActivity,,,系统安装 com.tencent.mm,com.tencent.mm.ui.LauncherUI,,,微信