From d73f0f137178faa36ebb7a7ed056035d969e5f4f Mon Sep 17 00:00:00 2001 From: tongtongstudio Date: Mon, 2 Sep 2024 09:29:00 +0800 Subject: [PATCH] =?UTF-8?q?version:1.8.9=20fix:=E4=BC=98=E5=8C=96=E8=8B=B1?= =?UTF-8?q?=E8=AF=AD=E7=95=8C=E9=9D=A2=E6=8A=A5=E9=94=99=20update:?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E9=A1=B5=E6=98=BE=E7=A4=BA=E4=BD=9C=E4=B8=9A?= =?UTF-8?q?=E5=88=86=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 4 +- app/src/main/AndroidManifest.xml | 26 +- .../uiui/zyos/activity/main/MainActivity.java | 64 ++++ .../zyos/activity/main/MainViewModel.java | 46 +++ .../zyos/activity/update/UpdateActivity.java | 85 ++++++ .../zyos/activity/update/UpdateViewModel.java | 18 ++ .../uiui/zyos/adapter/NewHomeworkAdapter.java | 66 ++++ .../main/java/com/uiui/zyos/bean/AppBase.java | 58 ++++ .../com/uiui/zyos/bean/AppUpdateInfo.java | 109 +++++++ .../com/uiui/zyos/bean/AriaDownloadInfo.java | 140 +++++++++ .../java/com/uiui/zyos/bean/HomeworkBean.java | 134 +++++++++ .../com/uiui/zyos/bean/HomeworkSubject.java | 26 ++ .../uiui/zyos/dialog/EnglishBasicsDialog.java | 1 + .../fragment/english/EnglishFragment.java | 2 +- .../uiui/zyos/fragment/user/UserFragment.java | 30 ++ .../zyos/fragment/user/UserViewModel.java | 31 ++ .../zyos/network/NetInterfaceManager.java | 100 ++++++- .../com/uiui/zyos/network/UrlAddress.java | 10 + .../uiui/zyos/network/api/GetHomeworkApi.java | 18 ++ .../zyos/network/api/HomeworkDetailApi.java | 17 ++ .../network/api/uiuios/CheckUpdateApi.java | 16 + .../uiui/zyos/service/DownloadService.java | 188 +++++++++++- .../com/uiui/zyos/service/SocketService.java | 2 +- .../java/com/uiui/zyos/utils/ApkUtils.java | 86 ++++++ .../java/com/uiui/zyos/utils/FileUtil.java | 214 +++++++++++++ .../com/uiui/zyos/utils/OpenApkUtils.java | 33 +- app/src/main/res/drawable-hdpi/icon_close.png | Bin 0 -> 1701 bytes .../main/res/drawable-hdpi/no_homework.png | Bin 0 -> 13295 bytes .../main/res/drawable/dialog_background.xml | 9 + .../res/drawable/item_homework_background.xml | 2 +- .../main/res/drawable/update_background.xml | 13 + .../res/drawable/update_cancel_background.xml | 13 + .../main/res/layout-land/fragment_user.xml | 91 +++++- .../main/res/layout-sw800dp/fragment_user.xml | 92 +++++- app/src/main/res/layout/activity_update.xml | 164 ++++++++++ app/src/main/res/layout/fragment_user.xml | 283 ++++++++++++------ app/src/main/res/layout/item_homework_new.xml | 79 +++++ app/src/main/res/values/colors.xml | 2 + app/src/main/res/xml/file_paths.xml | 18 ++ 39 files changed, 2154 insertions(+), 136 deletions(-) create mode 100644 app/src/main/java/com/uiui/zyos/activity/update/UpdateActivity.java create mode 100644 app/src/main/java/com/uiui/zyos/activity/update/UpdateViewModel.java create mode 100644 app/src/main/java/com/uiui/zyos/adapter/NewHomeworkAdapter.java create mode 100644 app/src/main/java/com/uiui/zyos/bean/AppBase.java create mode 100644 app/src/main/java/com/uiui/zyos/bean/AppUpdateInfo.java create mode 100644 app/src/main/java/com/uiui/zyos/bean/AriaDownloadInfo.java create mode 100644 app/src/main/java/com/uiui/zyos/bean/HomeworkBean.java create mode 100644 app/src/main/java/com/uiui/zyos/bean/HomeworkSubject.java create mode 100644 app/src/main/java/com/uiui/zyos/network/api/GetHomeworkApi.java create mode 100644 app/src/main/java/com/uiui/zyos/network/api/HomeworkDetailApi.java create mode 100644 app/src/main/java/com/uiui/zyos/network/api/uiuios/CheckUpdateApi.java create mode 100644 app/src/main/res/drawable-hdpi/icon_close.png create mode 100644 app/src/main/res/drawable-hdpi/no_homework.png create mode 100644 app/src/main/res/drawable/dialog_background.xml create mode 100644 app/src/main/res/drawable/update_background.xml create mode 100644 app/src/main/res/drawable/update_cancel_background.xml create mode 100644 app/src/main/res/layout/activity_update.xml create mode 100644 app/src/main/res/layout/item_homework_new.xml create mode 100644 app/src/main/res/xml/file_paths.xml diff --git a/app/build.gradle b/app/build.gradle index 9750ed5..b5457d5 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,8 +16,8 @@ android { minSdkVersion 24 targetSdkVersion 29 - versionCode 79 - versionName "1.8.7" + versionCode 81 + versionName "1.8.9" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 8b4a30e..1c97ea7 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -115,7 +115,7 @@ + android:screenOrientation="userLandscape" /> + android:screenOrientation="userLandscape" /> + --> + + + + + + implements RemoteManager.ConnectedListener { private static final String TAG = "MainActivity"; @@ -67,6 +74,8 @@ public class MainActivity extends BaseMvvmActivity() { + @Override + public void onChanged(AppUpdateInfo appUpdateInfo) { + mAppUpdateInfo = appUpdateInfo; + if (appUpdateInfo == null) { +// Toaster.show("已是最新版本"); + } else { + if (ApkUtils.isUpdate(MainActivity.this, appUpdateInfo)) { + Intent intent = new Intent(MainActivity.this, UpdateActivity.class); + intent.putExtra("appUpdateInfo", appUpdateInfo); + startActivity(intent); + Toaster.show("有新的版本需要更新"); + } else { +// Toaster.show("已是最新版本"); + } + } + } + }); + getStorgePermission(); registmNewAppReceiver(); registmUpdateAddressReceiver(); } @@ -418,6 +446,42 @@ public class MainActivity extends BaseMvvmActivity permissions, boolean allGranted) { + Log.e(TAG, "onGranted: permissions = " + permissions + " allGranted = " + allGranted); + if (!allGranted) { + Toaster.show("获取部分权限成功,但部分权限未正常授予"); + return; + } + Log.e(TAG, "onGranted: 获取权限成功"); + mViewModel.checkUpdate(); + } + + @Override + public void onDenied(@NonNull List permissions, boolean doNotAskAgain) { + Log.e(TAG, "onDenied: permissions = " + permissions + " doNotAskAgain = " + doNotAskAgain); + if (doNotAskAgain) { + Toaster.show("被永久拒绝授权,请手动授予权限"); + // 如果是被永久拒绝就跳转到应用权限系统设置页面 + XXPermissions.startPermissionActivity(MainActivity.this, permissions); + } else { + Log.e(TAG, "onGranted: 获取权限失败"); + } + } + }); + } + private String[] mLocationPermission = new String[]{ Permission.ACCESS_COARSE_LOCATION, Permission.ACCESS_FINE_LOCATION, diff --git a/app/src/main/java/com/uiui/zyos/activity/main/MainViewModel.java b/app/src/main/java/com/uiui/zyos/activity/main/MainViewModel.java index 4c6906e..ac253db 100644 --- a/app/src/main/java/com/uiui/zyos/activity/main/MainViewModel.java +++ b/app/src/main/java/com/uiui/zyos/activity/main/MainViewModel.java @@ -3,11 +3,15 @@ package com.uiui.zyos.activity.main; import android.text.TextUtils; import android.util.Log; +import androidx.lifecycle.MutableLiveData; + import com.google.gson.JsonObject; +import com.hjq.toast.Toaster; import com.trello.rxlifecycle4.RxLifecycle; import com.trello.rxlifecycle4.android.ActivityEvent; import com.uiui.zyos.BuildConfig; import com.uiui.zyos.base.mvvm.BaseViewModel; +import com.uiui.zyos.bean.AppUpdateInfo; import com.uiui.zyos.bean.BaseResponse; import com.uiui.zyos.databinding.ActivityMainBinding; import com.uiui.zyos.manager.RemoteManager; @@ -17,6 +21,7 @@ import com.uiui.zyos.utils.ApkUtils; import com.uiui.zyos.utils.AppUsedTimeUtils; import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; +import io.reactivex.rxjava3.annotations.NonNull; import io.reactivex.rxjava3.core.Observer; import io.reactivex.rxjava3.disposables.Disposable; import io.reactivex.rxjava3.schedulers.Schedulers; @@ -35,6 +40,46 @@ public class MainViewModel extends BaseViewModel mAppUpdateInfoData = new MutableLiveData<>(); + + public MutableLiveData getAppUpdateInfoData() { + return mAppUpdateInfoData; + } + + public void checkUpdate() { + NetInterfaceManager.getInstance().getCheckUpdateObservable(BuildConfig.APPLICATION_ID) + .compose(RxLifecycle.bindUntilEvent(getLifecycle(), ActivityEvent.DESTROY)) + .subscribe(new Observer>() { + @Override + public void onSubscribe(@NonNull Disposable d) { + Log.e("checkUpdate", "onSubscribe: "); + } + + @Override + public void onNext(@NonNull BaseResponse appUpdateInfoBaseResponse) { + Log.e("checkUpdate", "onNext: " + appUpdateInfoBaseResponse); + if (appUpdateInfoBaseResponse.code == 200) { + AppUpdateInfo appUpdateInfo = appUpdateInfoBaseResponse.data; + mAppUpdateInfoData.setValue(appUpdateInfo); + } else { + mAppUpdateInfoData.setValue(null); + } + } + + @Override + public void onError(@NonNull Throwable e) { + Log.e("checkUpdate", "onError: "); + Toaster.show("网络连接失败"); + } + + @Override + public void onComplete() { + Log.e("checkUpdate", "onComplete: "); + } + }); + } + + @Deprecated public void sendAPPUsage() { boolean activation = ActivationUtil.isActivation(getCtx()); if (!activation) { @@ -83,6 +128,7 @@ public class MainViewModel extends BaseViewModel { + + private AppUpdateInfo mAppInfoData; + + + @Override + protected int getLayoutId() { + return R.layout.activity_update; + } + + @Override + protected void initDataBinding() { + mViewModel.setCtx(this); + mViewModel.setLifecycle(getLifecycleSubject()); + mViewModel.setVDBinding(mViewDataBinding); + mViewDataBinding.setClick(new BtnClick()); + } + + @Override + protected void initView() { + + } + + @Override + protected void initData() { + Intent intent = getIntent(); + mAppInfoData = (AppUpdateInfo) intent.getSerializableExtra("appUpdateInfo"); + mViewDataBinding.setAppUpdateInfo(mAppInfoData); + mViewDataBinding.setMsg("检测到新版本,是否更新"); + } + + + public class BtnClick { + public void empty(View view){ + + } + + public void exit(View view) { + finish(); + } + + public void upgrade(View view) { + startService(new Intent(UpdateActivity.this, DownloadService.class)); + if (mAppInfoData != null) { + DownloadEntity entity = Aria.download(this).getFirstDownloadEntity(mAppInfoData.getApp_url()); + if (null != entity) { + if (entity.isComplete()) { + ApkUtils.installApkFile(UpdateActivity.this, entity.getFilePath()); + } else { + if (entity.getState() == STATE_RUNNING) { + Toaster.show("文件正在下载中"); + finish(); + } else { + Aria.download(this).resumeAllTask(); + Toaster.show("正在下载"); + finish(); + } + } + } else { + ApkUtils.checkAppUpdate(UpdateActivity.this, mAppInfoData); + Toaster.show("正在下载更新"); + finish(); + } + } + + } + } +} diff --git a/app/src/main/java/com/uiui/zyos/activity/update/UpdateViewModel.java b/app/src/main/java/com/uiui/zyos/activity/update/UpdateViewModel.java new file mode 100644 index 0000000..02a35fe --- /dev/null +++ b/app/src/main/java/com/uiui/zyos/activity/update/UpdateViewModel.java @@ -0,0 +1,18 @@ +package com.uiui.zyos.activity.update; + +import com.trello.rxlifecycle4.android.ActivityEvent; +import com.uiui.zyos.base.mvvm.BaseViewModel; +import com.uiui.zyos.databinding.ActivityUpdateBinding; + +public class UpdateViewModel extends BaseViewModel { + + @Override + public ActivityUpdateBinding getVDBinding() { + return binding; + } + + @Override + public void onDestroy() { + + } +} diff --git a/app/src/main/java/com/uiui/zyos/adapter/NewHomeworkAdapter.java b/app/src/main/java/com/uiui/zyos/adapter/NewHomeworkAdapter.java new file mode 100644 index 0000000..79f4846 --- /dev/null +++ b/app/src/main/java/com/uiui/zyos/adapter/NewHomeworkAdapter.java @@ -0,0 +1,66 @@ +package com.uiui.zyos.adapter; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.constraintlayout.widget.ConstraintLayout; +import androidx.recyclerview.widget.RecyclerView; + +import com.shehuan.niv.NiceImageView; +import com.uiui.zyos.R; +import com.uiui.zyos.bean.HomeworkBean; +import com.uiui.zyos.utils.GlideLoadUtils; + +import java.util.List; + +public class NewHomeworkAdapter extends RecyclerView.Adapter { + + private Context mContext; + private List mHomeworkList; + + public void setHomeworkList(List homeworkList) { + mHomeworkList = homeworkList; + notifyDataSetChanged(); + } + + @NonNull + @Override + public Holder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + mContext = parent.getContext(); + return new Holder(LayoutInflater.from(mContext).inflate(R.layout.item_homework_new, parent, false)); + } + + @Override + public void onBindViewHolder(@NonNull Holder holder, int position) { + HomeworkBean homeworkBean = mHomeworkList.get(position); + GlideLoadUtils.getInstance().glideLoad(mContext, homeworkBean.getFile_url(), holder.imageView, R.drawable.item_icon_homework); + holder.tv_content.setText(homeworkBean.getTitle()); + holder.tv_type.setText(homeworkBean.getContent()); + holder.tv_time.setText(homeworkBean.getCreated_at()); + } + + @Override + public int getItemCount() { + return mHomeworkList == null ? 0 : mHomeworkList.size(); + } + + class Holder extends RecyclerView.ViewHolder { + ConstraintLayout root; + NiceImageView imageView; + TextView tv_content, tv_type, tv_time; + + public Holder(@NonNull View itemView) { + super(itemView); + root = itemView.findViewById(R.id.root); + imageView = itemView.findViewById(R.id.imageView); + tv_content = itemView.findViewById(R.id.tv_content); + tv_type = itemView.findViewById(R.id.tv_type); + tv_time = itemView.findViewById(R.id.tv_time); + } + } +} diff --git a/app/src/main/java/com/uiui/zyos/bean/AppBase.java b/app/src/main/java/com/uiui/zyos/bean/AppBase.java new file mode 100644 index 0000000..977bae7 --- /dev/null +++ b/app/src/main/java/com/uiui/zyos/bean/AppBase.java @@ -0,0 +1,58 @@ +package com.uiui.zyos.bean; + +import androidx.annotation.NonNull; + +import com.google.gson.Gson; +import com.google.gson.JsonParser; + +import java.io.Serializable; + +public class AppBase implements Serializable { + private static final long serialVersionUID = -1084612101570534997L; + + int id; + String app_name; + String app_package; +// @SerializedName(value = "icon", alternate = "app_icon") + String icon; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getApp_name() { + return app_name; + } + + public void setApp_name(String app_name) { + this.app_name = app_name; + } + + public String getApp_package() { + return app_package; + } + + public void setApp_package(String app_package) { + this.app_package = app_package; + } + + public String getIcon() { + return icon; + } + + public void setIcon(String icon) { + this.icon = icon; + } + + + @NonNull + @Override + public String toString() { + return JsonParser.parseString(new Gson().toJson(this)).getAsJsonObject().toString(); + } + +} diff --git a/app/src/main/java/com/uiui/zyos/bean/AppUpdateInfo.java b/app/src/main/java/com/uiui/zyos/bean/AppUpdateInfo.java new file mode 100644 index 0000000..28ebda1 --- /dev/null +++ b/app/src/main/java/com/uiui/zyos/bean/AppUpdateInfo.java @@ -0,0 +1,109 @@ +package com.uiui.zyos.bean; + +import androidx.annotation.NonNull; + +import com.google.gson.Gson; +import com.google.gson.JsonParser; + +import java.io.Serializable; + +public class AppUpdateInfo implements Serializable { + private static final long serialVersionUID = -683006285701880863L; + + int id; + int app_id; + String app_version_name; + long app_version_code; + long app_size; + String app_desc; + String app_md5; + String app_url; + String is_forcedown; + AppBase app; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public int getApp_id() { + return app_id; + } + + public void setApp_id(int app_id) { + this.app_id = app_id; + } + + public String getApp_version_name() { + return app_version_name; + } + + public void setApp_version_name(String app_version_name) { + this.app_version_name = app_version_name; + } + + public long getApp_version_code() { + return app_version_code; + } + + public void setApp_version_code(long app_version_code) { + this.app_version_code = app_version_code; + } + + public long getApp_size() { + return app_size; + } + + public void setApp_size(long app_size) { + this.app_size = app_size; + } + + public String getApp_desc() { + return app_desc; + } + + public void setApp_desc(String app_desc) { + this.app_desc = app_desc; + } + + public String getApp_md5() { + return app_md5; + } + + public void setApp_md5(String app_md5) { + this.app_md5 = app_md5; + } + + public String getApp_url() { + return app_url; + } + + public void setApp_url(String app_url) { + this.app_url = app_url; + } + + public String getIs_forcedown() { + return is_forcedown; + } + + public void setIs_forcedown(String is_forcedown) { + this.is_forcedown = is_forcedown; + } + + public AppBase getApp() { + return app; + } + + public void setApp(AppBase app) { + this.app = app; + } + + @NonNull + @Override + public String toString() { + return JsonParser.parseString(new Gson().toJson(this)).getAsJsonObject().toString(); + } +} diff --git a/app/src/main/java/com/uiui/zyos/bean/AriaDownloadInfo.java b/app/src/main/java/com/uiui/zyos/bean/AriaDownloadInfo.java new file mode 100644 index 0000000..94d957a --- /dev/null +++ b/app/src/main/java/com/uiui/zyos/bean/AriaDownloadInfo.java @@ -0,0 +1,140 @@ +package com.uiui.zyos.bean; + +import androidx.annotation.NonNull; + +import com.google.gson.Gson; +import com.google.gson.JsonParser; + +import java.io.Serializable; + +public class AriaDownloadInfo implements Serializable { + private static final long serialVersionUID = -2835281454196323431L; + + int appId; + String appName; + String appPackage; + String appVersionName; + long appVersionCode; + String appUrl; + String appIcon; + long appSize; + String appMd5; + + public AriaDownloadInfo(int appId, String appName, String appPackage, String appVersionName, long appVersionCode, String appUrl, String appIcon, long appSize, String appMd5) { + this.appId = appId; + this.appName = appName; + this.appPackage = appPackage; + this.appVersionName = appVersionName; + this.appVersionCode = appVersionCode; + this.appUrl = appUrl; + this.appIcon = appIcon; + this.appSize = appSize; + this.appMd5 = appMd5; + } + + public int getAppId() { + return appId; + } + + public void setAppId(int appId) { + this.appId = appId; + } + + public String getAppName() { + return appName; + } + + public void setAppName(String appName) { + this.appName = appName; + } + + public String getAppPackage() { + return appPackage; + } + + public void setAppPackage(String appPackage) { + this.appPackage = appPackage; + } + + public String getAppVersionName() { + return appVersionName; + } + + public void setAppVersionName(String appVersionName) { + this.appVersionName = appVersionName; + } + + public long getAppVersionCode() { + return appVersionCode; + } + + public void setAppVersionCode(long appVersionCode) { + this.appVersionCode = appVersionCode; + } + + public String getAppUrl() { + return appUrl; + } + + public void setAppUrl(String appUrl) { + this.appUrl = appUrl; + } + + public String getAppIcon() { + return appIcon; + } + + public void setAppIcon(String appIcon) { + this.appIcon = appIcon; + } + + public long getAppSize() { + return appSize; + } + + public void setAppSize(long appSize) { + this.appSize = appSize; + } + + public String getAppMd5() { + return appMd5; + } + + public void setAppMd5(String appMd5) { + this.appMd5 = appMd5; + } + + @NonNull + @Override + public String toString() { + return JsonParser.parseString(new Gson().toJson(this)).getAsJsonObject().toString(); + } + + public static AriaDownloadInfo toAriaDownloadInfo(AppUpdateInfo appUpdateInfo) { + return new AriaDownloadInfo( + appUpdateInfo.getApp_id(), + appUpdateInfo.getApp().getApp_name(), + appUpdateInfo.getApp().getApp_package(), + appUpdateInfo.getApp_version_name(), + appUpdateInfo.getApp_version_code(), + appUpdateInfo.getApp_url(), + appUpdateInfo.getApp().getIcon(), + appUpdateInfo.getApp_size(), + appUpdateInfo.getApp_md5() + ); + } +// +// public static AriaDownloadInfo toAriaDownloadInfo(AppDetails appDetails) { +// return new AriaDownloadInfo( +// appDetails.getId(), +// appDetails.getApp_name(), +// appDetails.getApp_package(), +// appDetails.getApp_version_name(), +// appDetails.getApp_version_code(), +// appDetails.getApp_url(), +// appDetails.getApp_icon(), +// appDetails.getApp_size(), +// appDetails.getApp_md5() +// ); +// } +} diff --git a/app/src/main/java/com/uiui/zyos/bean/HomeworkBean.java b/app/src/main/java/com/uiui/zyos/bean/HomeworkBean.java new file mode 100644 index 0000000..f20b1bf --- /dev/null +++ b/app/src/main/java/com/uiui/zyos/bean/HomeworkBean.java @@ -0,0 +1,134 @@ +package com.uiui.zyos.bean; + +import java.io.Serializable; + +public class HomeworkBean implements Serializable { + private static final long serialVersionUID = 4974017718666880157L; + + int id; + int subject_id; + int status; + String sn; + String title; + String content; + String file_url; + String file_name; + int file_type; + int work_type; + String end_time; + String created_at; + String updated_at; + HomeworkSubject subject; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public int getSubject_id() { + return subject_id; + } + + public void setSubject_id(int subject_id) { + this.subject_id = subject_id; + } + + public int getStatus() { + return status; + } + + public void setStatus(int status) { + this.status = status; + } + + public String getSn() { + return sn; + } + + public void setSn(String sn) { + this.sn = sn; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public String getFile_url() { + return file_url; + } + + public void setFile_url(String file_url) { + this.file_url = file_url; + } + + public String getFile_name() { + return file_name; + } + + public void setFile_name(String file_name) { + this.file_name = file_name; + } + + public int getFile_type() { + return file_type; + } + + public void setFile_type(int file_type) { + this.file_type = file_type; + } + + public int getWork_type() { + return work_type; + } + + public void setWork_type(int work_type) { + this.work_type = work_type; + } + + public String getEnd_time() { + return end_time; + } + + public void setEnd_time(String end_time) { + this.end_time = end_time; + } + + public String getCreated_at() { + return created_at; + } + + public void setCreated_at(String created_at) { + this.created_at = created_at; + } + + public String getUpdated_at() { + return updated_at; + } + + public void setUpdated_at(String updated_at) { + this.updated_at = updated_at; + } + + public HomeworkSubject getSubject() { + return subject; + } + + public void setSubject(HomeworkSubject subject) { + this.subject = subject; + } +} diff --git a/app/src/main/java/com/uiui/zyos/bean/HomeworkSubject.java b/app/src/main/java/com/uiui/zyos/bean/HomeworkSubject.java new file mode 100644 index 0000000..3c58fce --- /dev/null +++ b/app/src/main/java/com/uiui/zyos/bean/HomeworkSubject.java @@ -0,0 +1,26 @@ +package com.uiui.zyos.bean; + +import java.io.Serializable; + +public class HomeworkSubject implements Serializable { + private static final long serialVersionUID = 8454145003419075553L; + + int id; + String name; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/app/src/main/java/com/uiui/zyos/dialog/EnglishBasicsDialog.java b/app/src/main/java/com/uiui/zyos/dialog/EnglishBasicsDialog.java index a913008..e0b2de0 100644 --- a/app/src/main/java/com/uiui/zyos/dialog/EnglishBasicsDialog.java +++ b/app/src/main/java/com/uiui/zyos/dialog/EnglishBasicsDialog.java @@ -22,6 +22,7 @@ public class EnglishBasicsDialog extends AlertDialog { private ConstraintLayout cl_sentence; private ConstraintLayout cl_patterns; private ConstraintLayout cl_writing; + public EnglishBasicsDialog(@NonNull Context context) { super(context, R.style.CustomDialog); this.mContext = context; diff --git a/app/src/main/java/com/uiui/zyos/fragment/english/EnglishFragment.java b/app/src/main/java/com/uiui/zyos/fragment/english/EnglishFragment.java index aac6706..2662709 100644 --- a/app/src/main/java/com/uiui/zyos/fragment/english/EnglishFragment.java +++ b/app/src/main/java/com/uiui/zyos/fragment/english/EnglishFragment.java @@ -73,7 +73,7 @@ public class EnglishFragment extends BaseDataBindingFragment() { @Override public void onChanged(Bitmap bitmap) { mViewDataBinding.ivDeviceQrcode.setImageBitmap(bitmap); } }); + mViewModel.mDesktopListIconData.observe(this, new Observer>() { @Override public void onChanged(ArrayList desktopIcons) { @@ -297,6 +310,7 @@ public class UserFragment extends BaseMvvmFragment() { @Override public void onChanged(Long time) { @@ -305,6 +319,22 @@ public class UserFragment extends BaseMvvmFragment>() { + @Override + public void onChanged(List homeworkBeans) { + mHomeworkAdapter.setHomeworkList(homeworkBeans); + if (homeworkBeans==null||homeworkBeans.isEmpty()){ + mViewDataBinding.llNodata.setVisibility(View.VISIBLE); + mViewDataBinding.rvHomework.setVisibility(View.GONE); + }else { + mViewDataBinding.llNodata.setVisibility(View.GONE); + mViewDataBinding.rvHomework.setVisibility(View.VISIBLE); + } + } + }); + + mViewModel.getHomework(); } @Override diff --git a/app/src/main/java/com/uiui/zyos/fragment/user/UserViewModel.java b/app/src/main/java/com/uiui/zyos/fragment/user/UserViewModel.java index 08a8760..d03799e 100644 --- a/app/src/main/java/com/uiui/zyos/fragment/user/UserViewModel.java +++ b/app/src/main/java/com/uiui/zyos/fragment/user/UserViewModel.java @@ -17,6 +17,7 @@ import com.uiui.zyos.base.mvvm.BaseViewModel; import com.uiui.zyos.bean.AppUsed; import com.uiui.zyos.bean.BaseResponse; import com.uiui.zyos.bean.DesktopIcon; +import com.uiui.zyos.bean.HomeworkBean; import com.uiui.zyos.bean.SnInfo; import com.uiui.zyos.bean.StudyStatBean; import com.uiui.zyos.config.CommonConfig; @@ -190,4 +191,34 @@ public class UserViewModel extends BaseViewModel> mHomeworkBeanListData = new MutableLiveData<>(); + + public void getHomework() { + NetInterfaceManager.getInstance().getHomeworkObservable() + .compose(RxLifecycle.bindUntilEvent(getLifecycle(), FragmentEvent.DESTROY)) + .subscribe(new Observer>>() { + @Override + public void onSubscribe(@NonNull Disposable d) { + Log.e("getHomework", "onSubscribe: "); + } + + @Override + public void onNext(@NonNull BaseResponse> listBaseResponse) { + Log.e("getHomework", "onNext: " + listBaseResponse); + List homeworkBeans = listBaseResponse.data; + mHomeworkBeanListData.setValue(homeworkBeans); + } + + @Override + public void onError(@NonNull Throwable e) { + Log.e("getHomework", "onError: " + e.getMessage()); + } + + @Override + public void onComplete() { + Log.e("getHomework", "onComplete: "); + } + }); + } } diff --git a/app/src/main/java/com/uiui/zyos/network/NetInterfaceManager.java b/app/src/main/java/com/uiui/zyos/network/NetInterfaceManager.java index 1e1fff7..21616a0 100644 --- a/app/src/main/java/com/uiui/zyos/network/NetInterfaceManager.java +++ b/app/src/main/java/com/uiui/zyos/network/NetInterfaceManager.java @@ -2,6 +2,7 @@ package com.uiui.zyos.network; import android.annotation.SuppressLint; import android.content.Context; +import android.os.Environment; import android.text.TextUtils; import android.util.Log; @@ -13,8 +14,10 @@ import com.trello.rxlifecycle4.android.ActivityEvent; import com.trello.rxlifecycle4.android.FragmentEvent; import com.uiui.zyos.alarm.AlarmUtils; import com.uiui.zyos.bean.AlarmClockData; +import com.uiui.zyos.bean.AppUpdateInfo; import com.uiui.zyos.bean.BaseResponse; import com.uiui.zyos.bean.GuideBean; +import com.uiui.zyos.bean.HomeworkBean; import com.uiui.zyos.bean.LessonApp; import com.uiui.zyos.bean.LessonJson; import com.uiui.zyos.bean.LessonSetting; @@ -30,12 +33,15 @@ import com.uiui.zyos.network.api.AppUsageRecordApi; import com.uiui.zyos.network.api.CloudLessonApi; import com.uiui.zyos.network.api.CloudLessonAppApi; import com.uiui.zyos.network.api.GetFilesApi; +import com.uiui.zyos.network.api.GetHomeworkApi; +import com.uiui.zyos.network.api.HomeworkDetailApi; import com.uiui.zyos.network.api.RunNewApp; import com.uiui.zyos.network.api.SNInfoApi; import com.uiui.zyos.network.api.StudyStatApi; import com.uiui.zyos.network.api.UpdateAddressApi; import com.uiui.zyos.network.api.UpdateAlarmClockApi; import com.uiui.zyos.network.api.UserInfoControl; +import com.uiui.zyos.network.api.uiuios.CheckUpdateApi; import com.uiui.zyos.network.interceptor.RepeatRequestInterceptor; import com.uiui.zyos.utils.OpenApkUtils; @@ -70,13 +76,15 @@ public class NetInterfaceManager { private CacheHelper mCacheHelper; private Retrofit mRetrofit; - private OkHttpClient okHttpClient; + private OkHttpClient mOkHttpClient; + private Retrofit mUiuiosRetrofit; + private OkHttpClient mUiuiosOkHttpClient; private final ConcurrentHashMap requestIdsMap = new ConcurrentHashMap<>(); //超时时间 - private static int timeOut = 30; + private static final int TIME_OUT = 30; // 缓存文件最大限制大小20M - private static long cacheSize = 1024 * 1024 * 64; + private static final long CACHE_SIZE = 1024 * 1024 * 64; public static final String HTTP_KEY = "YTM3YTAxNTJmMmZmNzkyM2E2YzIwZjlhZTc0NzNmMGI="; public static final String CUSTOM_REPEAT_REQ_PROTOCOL = "MY_CUSTOM_REPEAT_REQ_PROTOCOL"; @@ -84,31 +92,55 @@ public class NetInterfaceManager { private NetInterfaceManager(Context context) { this.mContext = context; this.mCacheHelper = new CacheHelper(context); - if (okHttpClient == null) { + if (mOkHttpClient == null) { //如果无法生存缓存文件目录,检测权限使用已经加上,检测手机是否把文件读写权限禁止了 OkHttpClient.Builder builder = new OkHttpClient.Builder(); - builder.connectTimeout(timeOut, TimeUnit.SECONDS); // 设置连接超时时间 - builder.writeTimeout(timeOut, TimeUnit.SECONDS);// 设置写入超时时间 - builder.readTimeout(timeOut, TimeUnit.SECONDS);// 设置读取数据超时时间 + 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()); // 设置缓存文件路径 - String cacheDirectory = mContext.getExternalCacheDir().getAbsolutePath() + "/OkHttpCache"; - Cache cache = new Cache(new File(cacheDirectory), cacheSize); + Cache cache = new Cache(new File(getCacheDir() + "/OkHttpCache"), CACHE_SIZE); builder.cache(cache);// 设置缓存 - okHttpClient = builder.build(); + mOkHttpClient = builder.build(); } if (mRetrofit == null) { mRetrofit = new Retrofit.Builder() - .client(okHttpClient) + .client(mOkHttpClient) .baseUrl(UrlAddress.ROOT_URL) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJava3CallAdapterFactory.create()) .build(); } + + if (mUiuiosOkHttpClient == 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(getCacheDir() + "/OkHttpCache"), CACHE_SIZE); + builder.cache(cache);// 设置缓存 + mUiuiosOkHttpClient = builder.build(); + } + + if (mUiuiosRetrofit == null) { + mUiuiosRetrofit = new Retrofit.Builder() + .client(mUiuiosOkHttpClient) + .baseUrl(UrlAddress.UIUIOS_ROOT_URL) + .addConverterFactory(GsonConverterFactory.create()) + .addCallAdapterFactory(RxJava3CallAdapterFactory.create()) + .build(); + } } /** @@ -131,6 +163,23 @@ public class NetInterfaceManager { Log.e("OKhttp ", " 打印HTTP请求完成 Headers \n"); } + private String getCacheDir() { + String cachePath; + if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) + || !Environment.isExternalStorageRemovable()) { + if (mContext.getExternalCacheDir() != null) { + cachePath = mContext.getExternalCacheDir().getPath(); + } else if (mContext.getExternalFilesDir("cache") != null) { + cachePath = mContext.getExternalFilesDir("cache").getPath(); + } else { + cachePath = mContext.getCacheDir().getPath(); + } + } else { + cachePath = mContext.getCacheDir().getPath(); + } + return cachePath; + } + public static void init(Context context) { if (INSTANCE == null) { INSTANCE = new NetInterfaceManager(context); @@ -145,7 +194,20 @@ public class NetInterfaceManager { } public OkHttpClient getOkHttpClient() { - return okHttpClient; + return mOkHttpClient; + } + + /** + * 检查更新 + * + * @param pkg + * @return + */ + public Observable> getCheckUpdateObservable(String pkg) { + return mUiuiosRetrofit.create(CheckUpdateApi.class) + .checkUpdate(pkg) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()); } /* @@ -234,6 +296,20 @@ public class NetInterfaceManager { .observeOn(AndroidSchedulers.mainThread()); } + public Observable>> getHomeworkObservable() { + return mRetrofit.create(GetHomeworkApi.class) + .getHomeworks(RemoteManager.getInstance().getSerial()) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()); + } + + public Observable> getHomeworkDetailObservable(int id) { + return mRetrofit.create(HomeworkDetailApi.class) + .getHomeworkDetail(RemoteManager.getInstance().getSerial(), id) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()); + } + /* * * execution diff --git a/app/src/main/java/com/uiui/zyos/network/UrlAddress.java b/app/src/main/java/com/uiui/zyos/network/UrlAddress.java index 9a4c0bc..7fb4ddc 100644 --- a/app/src/main/java/com/uiui/zyos/network/UrlAddress.java +++ b/app/src/main/java/com/uiui/zyos/network/UrlAddress.java @@ -24,7 +24,17 @@ public class UrlAddress { /*获取文件*/ public static final String GET_FILES = "file/getFiles"; + /*家庭作业列表*/ + public static final String GET_HOMEWORK = "homework/index"; + /*家庭作业详情*/ + public static final String GET_HOMEWORK_DETAIL = "homework/show"; + /*网课模式*/ public final static String GET_CLOUD_LESSON = "Control/getCloudLessonSetting"; public final static String GET_CLOUD_LESSON_APP = "Control/getCloudLessonApp"; + + + public static final String UIUIOS_ROOT_URL = "https://map.uiuios.com/android/"; + /*获取应用更新*/ + public static final String CHECK_UPDATE = "app/check-update"; } diff --git a/app/src/main/java/com/uiui/zyos/network/api/GetHomeworkApi.java b/app/src/main/java/com/uiui/zyos/network/api/GetHomeworkApi.java new file mode 100644 index 0000000..3a0896a --- /dev/null +++ b/app/src/main/java/com/uiui/zyos/network/api/GetHomeworkApi.java @@ -0,0 +1,18 @@ +package com.uiui.zyos.network.api; + +import com.uiui.zyos.bean.BaseResponse; +import com.uiui.zyos.bean.HomeworkBean; +import com.uiui.zyos.network.UrlAddress; + +import java.util.List; + +import io.reactivex.rxjava3.core.Observable; +import retrofit2.http.GET; +import retrofit2.http.Query; + +public interface GetHomeworkApi { + @GET(UrlAddress.GET_HOMEWORK) + Observable>> getHomeworks( + @Query("sn") String sn + ); +} diff --git a/app/src/main/java/com/uiui/zyos/network/api/HomeworkDetailApi.java b/app/src/main/java/com/uiui/zyos/network/api/HomeworkDetailApi.java new file mode 100644 index 0000000..b695306 --- /dev/null +++ b/app/src/main/java/com/uiui/zyos/network/api/HomeworkDetailApi.java @@ -0,0 +1,17 @@ +package com.uiui.zyos.network.api; + +import com.uiui.zyos.bean.BaseResponse; +import com.uiui.zyos.bean.HomeworkBean; +import com.uiui.zyos.network.UrlAddress; + +import io.reactivex.rxjava3.core.Observable; +import retrofit2.http.GET; +import retrofit2.http.Query; + +public interface HomeworkDetailApi { + @GET(UrlAddress.GET_HOMEWORK_DETAIL) + Observable> getHomeworkDetail( + @Query("sn") String sn, + @Query("id") int id + ); +} diff --git a/app/src/main/java/com/uiui/zyos/network/api/uiuios/CheckUpdateApi.java b/app/src/main/java/com/uiui/zyos/network/api/uiuios/CheckUpdateApi.java new file mode 100644 index 0000000..fdf66bd --- /dev/null +++ b/app/src/main/java/com/uiui/zyos/network/api/uiuios/CheckUpdateApi.java @@ -0,0 +1,16 @@ +package com.uiui.zyos.network.api.uiuios; + +import com.uiui.zyos.bean.AppUpdateInfo; +import com.uiui.zyos.bean.BaseResponse; +import com.uiui.zyos.network.UrlAddress; + +import io.reactivex.rxjava3.core.Observable; +import retrofit2.http.GET; +import retrofit2.http.Query; + +public interface CheckUpdateApi { + @GET(UrlAddress.CHECK_UPDATE) + Observable> checkUpdate( + @Query("app_package") String app_package + ); +} diff --git a/app/src/main/java/com/uiui/zyos/service/DownloadService.java b/app/src/main/java/com/uiui/zyos/service/DownloadService.java index cc70e8e..c7b1ef5 100644 --- a/app/src/main/java/com/uiui/zyos/service/DownloadService.java +++ b/app/src/main/java/com/uiui/zyos/service/DownloadService.java @@ -1,13 +1,33 @@ package com.uiui.zyos.service; +import android.app.NotificationChannel; +import android.app.NotificationManager; +import android.app.PendingIntent; import android.app.Service; import android.content.Intent; +import android.graphics.BitmapFactory; +import android.net.Uri; +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 androidx.core.content.FileProvider; + import com.arialyy.annotations.Download; import com.arialyy.aria.core.Aria; import com.arialyy.aria.core.task.DownloadTask; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.hjq.toast.Toaster; +import com.uiui.zyos.R; +import com.uiui.zyos.bean.AriaDownloadInfo; +import com.uiui.zyos.utils.ApkUtils; + +import java.io.File; +import java.lang.reflect.Type; public class DownloadService extends Service { private static final String TAG = "DownloadService"; @@ -23,13 +43,17 @@ public class DownloadService extends Service { @Override public void onCreate() { super.onCreate(); - Aria.init(this); Aria.download(this).register(); + + + mNotificationManagerCompat = NotificationManagerCompat.from(this); + createNotificationChannel(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { - return super.onStartCommand(intent, flags, startId); + Log.e(TAG, "onStartCommand: " + intent); + return START_STICKY; } @Override @@ -37,20 +61,172 @@ public class DownloadService extends Service { super.onDestroy(); } - //在这里处理任务执行中的状态,如进度进度条的刷新 + private static final String CHANNEL_ID = "CHANNEL_ID"; + private static final String CHANNEL_NAME = "系统通知"; + private static final String CHANNEL_DESCRIPTION = "关怀桌面通知"; + + private static final String CHANNEL_DOWNLOAD = "DOWNLOAD_CHANNEL"; + private static final String CHANNEL_DOWNLOAD_NAME = "下载管理"; + private static final String CHANNEL_DOWNLOAD_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 NotificationManagerCompat mNotificationManagerCompat; + private int NotificationID = 7890; + + private void sendSimpleNotification() { + Intent intent = new Intent(this, DownloadService.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()); + } + + private void sendDownloadRunning(AriaDownloadInfo ariaDownloadInfo, int progress) { + NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_DOWNLOAD) + .setSmallIcon(R.mipmap.ic_launcher) + .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher)) + .setContentTitle(ariaDownloadInfo.getAppName()) + .setContentText("下载中:" + progress + "%") + .setAutoCancel(true) + .setShowWhen(true) + .setOngoing(false) + .setOnlyAlertOnce(true) + .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()); + } + + private void sendDownloadComplete(AriaDownloadInfo ariaDownloadInfo, String path) { + NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_DOWNLOAD) + .setSmallIcon(R.mipmap.ic_launcher) + .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher)) + .setContentTitle(ariaDownloadInfo.getAppName()) + .setContentText("下载完成") + .setAutoCancel(true) + .setShowWhen(true) + .setOngoing(false) + .setOnlyAlertOnce(true) + .setPriority(NotificationCompat.PRIORITY_HIGH) + .setContentIntent(createIntent(path)); + // notificationId is a unique int for each notification that you must define + mNotificationManagerCompat.notify(ariaDownloadInfo.getAppId(), builder.build()); + } + + /** + * 设置通知点击事件 + * + * @return 点击事件 + */ + private PendingIntent createIntent(String path) { + File file = new File(path); + Intent intent = new Intent(Intent.ACTION_VIEW); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + //注意第二个参数,要保持和manifest中android:authorities的值相同 + Uri uri = FileProvider.getUriForFile(DownloadService.this, + getPackageName() + ".FileProvider", file); + intent.setDataAndType(uri, "application/vnd.android.package-archive"); + } else { + intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive"); + } + PendingIntent pendingIntent = PendingIntent.getActivity(DownloadService.this, 0, intent, + PendingIntent.FLAG_UPDATE_CURRENT); + return pendingIntent; + } + + private void sendDownloadFail(AriaDownloadInfo ariaDownloadInfo) { + NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_DOWNLOAD) + .setSmallIcon(R.mipmap.ic_launcher) + .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher)) + .setContentTitle(ariaDownloadInfo.getAppName()) + .setContentText("下载失败") + .setAutoCancel(true) + .setShowWhen(true) + .setOngoing(false) + .setOnlyAlertOnce(true) + .setPriority(NotificationCompat.PRIORITY_HIGH); + // notificationId is a unique int for each notification that you must define + mNotificationManagerCompat.notify(ariaDownloadInfo.getAppId(), builder.build()); + } + @Download.onTaskRunning - protected void running(DownloadTask task) { - Log.e("aria", "正在下载:" + task.getPercent() + ":" + task.getExtendField()); + void running(DownloadTask task) { + String jsonString = task.getExtendField(); + Log.e(TAG, "running: " + "正在下载:" + task.getPercent() + "% " + jsonString); + AriaDownloadInfo ariaDownloadInfo = getAriaDownloadInfo(jsonString); + if (ariaDownloadInfo != null) { + Toaster.show("正在下载: " + ariaDownloadInfo.getAppName() + "\t" + task.getPercent() + "%"); + sendDownloadRunning(ariaDownloadInfo, task.getPercent()); + } } @Download.onTaskComplete void taskComplete(DownloadTask task) { - //在这里处理任务完成的状态 Log.e(TAG, "taskComplete: " + task.getFilePath()); + ApkUtils.installApkFile(DownloadService.this, task.getFilePath()); + String jsonString = task.getExtendField(); + Log.e(TAG, "taskComplete: " + "下载完成:" + jsonString); + AriaDownloadInfo ariaDownloadInfo = getAriaDownloadInfo(jsonString); + if (ariaDownloadInfo != null) { + Toaster.show("下载完成: " + "\t" + ariaDownloadInfo.getAppName()); + sendDownloadComplete(ariaDownloadInfo, task.getFilePath()); + } } @Download.onTaskFail void taskFail(DownloadTask task, Exception e) { + Log.e(TAG, "taskFail: "); + String jsonString = task.getExtendField(); + Log.e(TAG, "taskFail: " + "下载失败:" + jsonString); + AriaDownloadInfo ariaDownloadInfo = getAriaDownloadInfo(jsonString); + if (ariaDownloadInfo != null) { + Toaster.show("下载失败: " + "\t" + ariaDownloadInfo.getAppName()); + sendDownloadFail(ariaDownloadInfo); + } + } + private AriaDownloadInfo getAriaDownloadInfo(String jsonString) { + if (!TextUtils.isEmpty(jsonString)) { + Gson gson = new Gson(); + Type type = new TypeToken() { + }.getType(); + AriaDownloadInfo ariaDownloadInfo = null; + try { + ariaDownloadInfo = gson.fromJson(jsonString, type); + } catch (Exception e) { + Log.e(TAG, "getAriaDownloadInfo: " + e.getMessage()); + } + return ariaDownloadInfo; + } else { + return null; + } } } diff --git a/app/src/main/java/com/uiui/zyos/service/SocketService.java b/app/src/main/java/com/uiui/zyos/service/SocketService.java index 73435a9..712e7ed 100644 --- a/app/src/main/java/com/uiui/zyos/service/SocketService.java +++ b/app/src/main/java/com/uiui/zyos/service/SocketService.java @@ -57,7 +57,7 @@ import io.reactivex.rxjava3.functions.Consumer; * 3.设备用户解除绑定后,断开websocket 等待5秒 再重新链接websocket 以刷新用户关联 */ public class SocketService extends Service implements NetworkUtils.OnNetworkStatusChangedListener { - private final static String TAG = "JWebSocketClientService"; + private static final String TAG = "JWebSocketClientService"; public JWebSocketClient mJWebSocketClient; // private SocketServiceBinder mBinder = new SocketServiceBinder(); diff --git a/app/src/main/java/com/uiui/zyos/utils/ApkUtils.java b/app/src/main/java/com/uiui/zyos/utils/ApkUtils.java index 39a9ebe..e91d6a4 100644 --- a/app/src/main/java/com/uiui/zyos/utils/ApkUtils.java +++ b/app/src/main/java/com/uiui/zyos/utils/ApkUtils.java @@ -9,6 +9,7 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageInstaller; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; +import android.net.Uri; import android.os.Binder; import android.os.Build; import android.provider.Settings; @@ -16,8 +17,10 @@ import android.text.TextUtils; import android.util.Log; import androidx.annotation.RequiresApi; +import androidx.core.content.FileProvider; import com.uiui.zyos.BuildConfig; +import com.uiui.zyos.bean.AppUpdateInfo; import com.uiui.zyos.bean.DesktopIcon; import com.uiui.zyos.manager.RemoteManager; import com.uiui.zyos.receiver.InstallResultReceiver; @@ -633,4 +636,87 @@ public class ApkUtils { context.startActivity(i); } } + + + public static boolean isUpdate(Context context, AppUpdateInfo appUpdateInfo) { + String packageName = appUpdateInfo.getApp().getApp_package(); + long versionCode = appUpdateInfo.getApp_version_code(); + return isUpdate(context, packageName, versionCode); + } + + public static boolean isUpdate(Context context, String packageName, long versionCode) { + PackageInfo packageInfo = null; + try { + packageInfo = context.getPackageManager().getPackageInfo(packageName, 0); + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); + } + if (packageInfo == null) { + return true; + } else { + long appVersionCode; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + appVersionCode = packageInfo.getLongVersionCode(); + } else { + appVersionCode = packageInfo.versionCode; + } + if (appVersionCode < versionCode) { + return true; + } else { + Log.e(TAG, "checkUpdate: " + packageName + "\t已经是最新版"); + return false; + } + } + } + + public static void installApkFile(Context context, String path) { + File apk = new File(path); + installApkFile(context, apk); + } + + public static void checkAppUpdate(Context context, AppUpdateInfo appUpdateInfo) { + String packageName = appUpdateInfo.getApp().getApp_package(); + long versionCode = appUpdateInfo.getApp_version_code(); + String url = appUpdateInfo.getApp_url(); + PackageInfo packageInfo = null; + try { + packageInfo = context.getPackageManager().getPackageInfo(packageName, 0); + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); + } + if (packageInfo == null) { + FileUtil.ariaDownload(context, url, appUpdateInfo); + } else { + long appVersionCode; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + appVersionCode = packageInfo.getLongVersionCode(); + } else { + appVersionCode = packageInfo.versionCode; + } + if (appVersionCode < versionCode) { + FileUtil.ariaDownload(context, url, appUpdateInfo); + } else { + Log.e(TAG, "checkUpdate: " + packageName + "\t已经是最新版"); + } + } + } + + public static void installApkFile(Context context, File file) { + Intent intent = new Intent(Intent.ACTION_VIEW); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + //注意第二个参数,要保持和manifest中android:authorities的值相同 + Uri uri = FileProvider.getUriForFile(context, + context.getPackageName() + ".FileProvider", file); + intent.setDataAndType(uri, "application/vnd.android.package-archive"); + } else { + intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive"); + } + try { + context.startActivity(intent); + } catch (Exception e) { + e.printStackTrace(); + } + } } diff --git a/app/src/main/java/com/uiui/zyos/utils/FileUtil.java b/app/src/main/java/com/uiui/zyos/utils/FileUtil.java index 8debaeb..db123db 100644 --- a/app/src/main/java/com/uiui/zyos/utils/FileUtil.java +++ b/app/src/main/java/com/uiui/zyos/utils/FileUtil.java @@ -1,10 +1,33 @@ package com.uiui.zyos.utils; +import android.content.ContentResolver; +import android.content.Context; +import android.database.Cursor; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.net.Uri; +import android.os.Environment; +import android.provider.MediaStore; import android.text.TextUtils; +import android.util.Log; +import androidx.core.content.ContextCompat; + +import com.arialyy.aria.core.Aria; +import com.uiui.zyos.bean.AppUpdateInfo; +import com.uiui.zyos.bean.AriaDownloadInfo; +import com.uiui.zyos.gson.GsonUtils; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.math.BigInteger; +import java.security.MessageDigest; import java.util.HashSet; public class FileUtil { + private static final String TAG = "FileUtil"; + public static String getFileType(String url) { if (url.indexOf("/") == -1) { return url.substring(url.indexOf("."), url.length()); @@ -14,6 +37,10 @@ public class FileUtil { } } + public static boolean isLocalPath(String path) { + return path.startsWith(File.separator); + } + private static HashSet videoFormat = new HashSet() {{ this.add(".mp4"); this.add(".avi"); @@ -51,4 +78,191 @@ public class FileUtil { } } + public static File uriToFile(Uri uri, Context context) { + String path = null; + if ("file".equals(uri.getScheme())) { + path = uri.getEncodedPath(); + if (path != null) { + path = Uri.decode(path); + ContentResolver cr = context.getContentResolver(); + StringBuffer buff = new StringBuffer(); + buff.append("(").append(MediaStore.Images.ImageColumns.DATA).append("=").append("'" + path + "'").append(")"); + Cursor cur = cr.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, new String[]{MediaStore.Images.ImageColumns._ID, MediaStore.Images.ImageColumns.DATA}, buff.toString(), null, null); + int index = 0; + int dataIdx = 0; + for (cur.moveToFirst(); !cur.isAfterLast(); cur.moveToNext()) { + index = cur.getColumnIndex(MediaStore.Images.ImageColumns._ID); + index = cur.getInt(index); + dataIdx = cur.getColumnIndex(MediaStore.Images.ImageColumns.DATA); + path = cur.getString(dataIdx); + } + cur.close(); + if (index == 0) { + } else { + Uri u = Uri.parse("content://media/external/images/media/" + index); + System.out.println("temp uri is :" + u); + } + } + if (path != null) { + return new File(path); + } + } else if ("content".equals(uri.getScheme())) { + // 4.2.2以后 + String[] proj = {MediaStore.Images.Media.DATA}; + Cursor cursor = context.getContentResolver().query(uri, proj, null, null, null); + if (cursor.moveToFirst()) { + int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); + path = cursor.getString(columnIndex); + } + cursor.close(); + + return new File(path); + } else { + //Log.i(TAG, "Uri Scheme:" + uri.getScheme()); + return new File(uri.toString()); + } + return null; + } + + /** + * drawable转为file + * + * @param drawableId drawable的ID + * @param fileName 转换后的文件名 + * @return + */ + public static File drawableToFile(Context context, int drawableId, String fileName) { +// InputStream is = view.getContext().getResources().openRawResource(R.drawable.logo); + Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), drawableId); +// Bitmap bitmap = BitmapFactory.decodeStream(is); + String defaultPath = context.getFilesDir().getAbsolutePath() + "/defaultGoodInfo"; + File file = new File(defaultPath); + if (!file.exists()) { + file.mkdirs(); + } + String defaultImgPath = defaultPath + "/" + fileName; + file = new File(defaultImgPath); + try { + file.createNewFile(); + FileOutputStream fOut = new FileOutputStream(file); + bitmap.compress(Bitmap.CompressFormat.PNG, 20, fOut); +// is.close(); + fOut.flush(); + fOut.close(); + } catch (Exception e) { + e.printStackTrace(); + } + return file; + } + + /** + * bitmap + * + * @param bitmap bitmap + * @param fileName 转换后的文件名 + * @return + */ + public static File bitmapToFile(Context context, Bitmap bitmap, String fileName) { + String defaultPath = context.getFilesDir().getAbsolutePath() + "/defaultGoodInfo"; + File file = new File(defaultPath); + if (!file.exists()) { + file.mkdirs(); + } + String defaultImgPath = defaultPath + "/" + fileName; + file = new File(defaultImgPath); + try { + file.createNewFile(); + FileOutputStream fOut = new FileOutputStream(file); + bitmap.compress(Bitmap.CompressFormat.PNG, 100, fOut); +// is.close(); + fOut.flush(); + fOut.close(); + } catch (Exception e) { + e.printStackTrace(); + } + return file; + } + + + public static String getFileNamefromURL(String url) { + int position = url.lastIndexOf("/"); + return url.substring(position + 1); + } + + /** + * 获取单个文件的MD5值 + * + * @param file 文件 + * @return + */ + + public static String getFileMd5(File file) { + if (!file.isFile()) { + return ""; + } + MessageDigest digest = null; + FileInputStream in = null; + byte buffer[] = new byte[1024]; + int len; + try { + digest = MessageDigest.getInstance("MD5"); + in = new FileInputStream(file); + while ((len = in.read(buffer, 0, 1024)) != -1) { + digest.update(buffer, 0, len); + } + in.close(); + } catch (Exception e) { + e.printStackTrace(); + return ""; + } + BigInteger bigInt = new BigInteger(1, digest.digest()); + return bigInt.toString(32); + } + + public static String getDownLoadPath(Context context) { + String path = ContextCompat.getExternalFilesDirs(context, Environment.DIRECTORY_DOWNLOADS)[0].getAbsolutePath(); + return path + File.separator; + } + +// public static void ariaDownload(Context context, String url, AppDetails appDetails) { +// Log.e(TAG, "ariaDownload: " + appDetails); +// AriaDownloadInfo ariaDownloadInfo = AriaDownloadInfo.toAriaDownloadInfo(appDetails); +// ariaDownload(context, url, ariaDownloadInfo); +// } + + public static void ariaDownload(Context context, String url, AppUpdateInfo appUpdateInfo) { + Log.e(TAG, "ariaDownload: " + appUpdateInfo); + AriaDownloadInfo ariaDownloadInfo = AriaDownloadInfo.toAriaDownloadInfo(appUpdateInfo); + ariaDownload(context, url, ariaDownloadInfo); + } + + public static void ariaDownload(Context context, String url, AriaDownloadInfo ariaDownloadInfo) { + Log.e(TAG, "ariaDownload: " + ariaDownloadInfo); + String fileName = getFileNamefromURL(url); + String app_md5 = ariaDownloadInfo.getAppMd5(); + Log.e("ariaDownload", "app_md5 = " + app_md5); + File file = new File(getDownLoadPath(context) + fileName); + if (file.exists() && !file.isDirectory()) { + String fileMd5 = com.blankj.utilcode.util.FileUtils.getFileMD5ToString(file); + Log.e("ariaDownload", "fileMD5 = " + fileMd5); + if (fileMd5.equalsIgnoreCase(app_md5)) { + ApkUtils.installApkFile(context, file); + } else { + file.delete(); + Aria.download(context) + .load(url) //读取下载地址 + .setFilePath(getDownLoadPath(context) + fileName) + .ignoreFilePathOccupy() + .setExtendField(GsonUtils.toJSONString(ariaDownloadInfo)) + .create(); //启动下载} + } + } else { + Aria.download(context) + .load(url) //读取下载地址 + .setFilePath(getDownLoadPath(context) + fileName) + .ignoreFilePathOccupy() + .setExtendField(GsonUtils.toJSONString(ariaDownloadInfo)) + .create(); //启动下载} + } + } } diff --git a/app/src/main/java/com/uiui/zyos/utils/OpenApkUtils.java b/app/src/main/java/com/uiui/zyos/utils/OpenApkUtils.java index bb7e54b..265c9d5 100644 --- a/app/src/main/java/com/uiui/zyos/utils/OpenApkUtils.java +++ b/app/src/main/java/com/uiui/zyos/utils/OpenApkUtils.java @@ -21,6 +21,7 @@ import com.uiui.zyos.config.CommonConfig; import com.uiui.zyos.jxw.JxwPackageConfig; import java.lang.reflect.Type; +import java.math.BigDecimal; import java.util.HashMap; import java.util.HashSet; import java.util.Set; @@ -383,15 +384,29 @@ public class OpenApkUtils { if (packageInfo == null) { return false; } - long appVersionCode; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { - appVersionCode = packageInfo.getLongVersionCode(); - } else { - appVersionCode = packageInfo.versionCode; - } - if (appVersionCode > 10) { - return false; - } else { +// long appVersionCode; +// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { +// appVersionCode = packageInfo.getLongVersionCode(); +// } else { +// appVersionCode = packageInfo.versionCode; +// } +// if (appVersionCode > 10) { +// return false; +// } else { +// return true; +// } + String versionName = packageInfo.versionName; + Log.e(TAG, "isNewAiApp: versionName = " + versionName); + try { + BigDecimal version = new BigDecimal("20240527"); + BigDecimal bigDecimal = new BigDecimal(versionName); + if (bigDecimal.compareTo(version) > 0) { + return true; + } else { + return false; + } + } catch (Exception e) { + Log.e(TAG, "isNewAiApp: " + e.getMessage()); return true; } } diff --git a/app/src/main/res/drawable-hdpi/icon_close.png b/app/src/main/res/drawable-hdpi/icon_close.png new file mode 100644 index 0000000000000000000000000000000000000000..9ebcb0bdeb422cf2d31ca104d46a721006051d43 GIT binary patch literal 1701 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 aYCSDxj@mGg1L+?;04+6r)mjzXsQ&@dq28td literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/dialog_background.xml b/app/src/main/res/drawable/dialog_background.xml new file mode 100644 index 0000000..eaf60cf --- /dev/null +++ b/app/src/main/res/drawable/dialog_background.xml @@ -0,0 +1,9 @@ + + + + + + + diff --git a/app/src/main/res/drawable/item_homework_background.xml b/app/src/main/res/drawable/item_homework_background.xml index f407ba1..2b6061e 100644 --- a/app/src/main/res/drawable/item_homework_background.xml +++ b/app/src/main/res/drawable/item_homework_background.xml @@ -1,7 +1,7 @@ - + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/update_cancel_background.xml b/app/src/main/res/drawable/update_cancel_background.xml new file mode 100644 index 0000000..58247be --- /dev/null +++ b/app/src/main/res/drawable/update_cancel_background.xml @@ -0,0 +1,13 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout-land/fragment_user.xml b/app/src/main/res/layout-land/fragment_user.xml index 090f723..6eddf60 100644 --- a/app/src/main/res/layout-land/fragment_user.xml +++ b/app/src/main/res/layout-land/fragment_user.xml @@ -340,7 +340,7 @@ android:id="@+id/cl_activation" android:layout_width="match_parent" android:layout_height="match_parent" - android:visibility="visible"> + android:visibility="gone"> + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout-sw800dp/fragment_user.xml b/app/src/main/res/layout-sw800dp/fragment_user.xml index 45f6f89..c3d7d8c 100644 --- a/app/src/main/res/layout-sw800dp/fragment_user.xml +++ b/app/src/main/res/layout-sw800dp/fragment_user.xml @@ -458,7 +458,7 @@ android:id="@+id/cl_app" android:layout_width="match_parent" android:layout_height="match_parent" - android:visibility="visible"> + android:visibility="gone"> + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_update.xml b/app/src/main/res/layout/activity_update.xml new file mode 100644 index 0000000..6e6d92d --- /dev/null +++ b/app/src/main/res/layout/activity_update.xml @@ -0,0 +1,164 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_user.xml b/app/src/main/res/layout/fragment_user.xml index 348bfbd..6eddf60 100644 --- a/app/src/main/res/layout/fragment_user.xml +++ b/app/src/main/res/layout/fragment_user.xml @@ -115,41 +115,6 @@ app:layout_constraintStart_toEndOf="@+id/iv_speaker" app:layout_constraintTop_toTopOf="parent" /> - - - - - - - - + android:visibility="gone"> + + + + + + + app:layout_constraintTop_toBottomOf="@+id/cl_bind_statu" /> - + + android:visibility="visible"> - - - - - + app:layout_constraintTop_toTopOf="parent"> - + + + + + + + + + @@ -346,7 +340,7 @@ android:id="@+id/cl_activation" android:layout_width="match_parent" android:layout_height="match_parent" - android:visibility="visible"> + android:visibility="gone"> @@ -534,6 +529,96 @@ app:layout_constraintTop_toTopOf="@+id/rv_app" /> + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/item_homework_new.xml b/app/src/main/res/layout/item_homework_new.xml new file mode 100644 index 0000000..43eee73 --- /dev/null +++ b/app/src/main/res/layout/item_homework_new.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 947f9f5..16dd6a1 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -39,4 +39,6 @@ #F3F3F3 #646464 + #98999a + diff --git a/app/src/main/res/xml/file_paths.xml b/app/src/main/res/xml/file_paths.xml new file mode 100644 index 0000000..c69abbb --- /dev/null +++ b/app/src/main/res/xml/file_paths.xml @@ -0,0 +1,18 @@ + + + + + + + +