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 0000000..9ebcb0b Binary files /dev/null and b/app/src/main/res/drawable-hdpi/icon_close.png differ diff --git a/app/src/main/res/drawable-hdpi/no_homework.png b/app/src/main/res/drawable-hdpi/no_homework.png new file mode 100644 index 0000000..3686009 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/no_homework.png differ 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 @@ + + + + + + + +