|
|
@@ -0,0 +1,578 @@
|
|
|
+package com.atmob.task.adapter;
|
|
|
+
|
|
|
+import android.annotation.SuppressLint;
|
|
|
+import android.os.Bundle;
|
|
|
+import android.text.TextUtils;
|
|
|
+import android.util.Log;
|
|
|
+import android.view.LayoutInflater;
|
|
|
+import android.view.View;
|
|
|
+import android.view.ViewGroup;
|
|
|
+import android.widget.Toast;
|
|
|
+
|
|
|
+import androidx.annotation.IntegerRes;
|
|
|
+import androidx.annotation.NonNull;
|
|
|
+import androidx.annotation.Nullable;
|
|
|
+import androidx.recyclerview.widget.AsyncListDiffer;
|
|
|
+import androidx.recyclerview.widget.DiffUtil;
|
|
|
+import androidx.recyclerview.widget.RecyclerView;
|
|
|
+
|
|
|
+import com.atmob.task.AppTaskAdapter;
|
|
|
+import com.atmob.task.bean.AdAppInfoData;
|
|
|
+import com.atmob.task.bean.AppTaskBean;
|
|
|
+import com.atmob.task.bean.AppTaskDownloadWrapper;
|
|
|
+import com.atmob.task.data.LocalData;
|
|
|
+import com.atmob.task.utils.AppTaskEvent;
|
|
|
+import com.atmob.task.utils.InstallFaultToleranceUtils;
|
|
|
+import com.atmob.task.utils.RetrofitDownloader;
|
|
|
+import com.atmob.utils.AppInfoUtils;
|
|
|
+import com.atmob.utils.ResUtils;
|
|
|
+import com.atmob.utils.RxSchedulersUtils;
|
|
|
+import com.atmob.utils.Utils;
|
|
|
+
|
|
|
+import java.io.File;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.Collections;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.Iterator;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+
|
|
|
+import atmob.io.reactivex.rxjava3.core.Completable;
|
|
|
+import atmob.io.reactivex.rxjava3.core.CompletableObserver;
|
|
|
+import atmob.io.reactivex.rxjava3.core.Observable;
|
|
|
+import atmob.io.reactivex.rxjava3.core.Observer;
|
|
|
+import atmob.io.reactivex.rxjava3.disposables.CompositeDisposable;
|
|
|
+import atmob.io.reactivex.rxjava3.disposables.Disposable;
|
|
|
+import atmob.io.reactivex.rxjava3.schedulers.Schedulers;
|
|
|
+
|
|
|
+public class AppTaskItemAdapter extends RecyclerView.Adapter<AppTaskItemAdapter.AppTaskItemViewHolder> {
|
|
|
+
|
|
|
+ private static final String TAG = AppTaskItemAdapter.class.getSimpleName();
|
|
|
+
|
|
|
+ private static final String DIR_PATH = Utils.getContext().getExternalCacheDir().getPath();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 安装成功后, 是否强制打开
|
|
|
+ */
|
|
|
+ private static final boolean FORCE_OPEN = true;
|
|
|
+
|
|
|
+ private final HashMap<Long, String> potentialInstalledList = new HashMap<>();
|
|
|
+
|
|
|
+ private final AsyncListDiffer<AppTaskDownloadWrapper> asyncListDiffer = new AsyncListDiffer<>(this, new DiffCallback());
|
|
|
+
|
|
|
+ private final CompositeDisposable compositeDisposable;
|
|
|
+
|
|
|
+ private OnItemActionCallback onItemActionCallback;
|
|
|
+
|
|
|
+ private AppTaskAdapter appTaskAdapter;
|
|
|
+
|
|
|
+ public AppTaskItemAdapter(AppTaskAdapter appTaskAdapter, CompositeDisposable compositeDisposable) {
|
|
|
+ this.compositeDisposable = compositeDisposable;
|
|
|
+ this.appTaskAdapter = appTaskAdapter;
|
|
|
+ }
|
|
|
+
|
|
|
+ @NonNull
|
|
|
+ @Override
|
|
|
+ public AppTaskItemViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
|
|
+ if (appTaskAdapter == null) {
|
|
|
+ throw new IllegalStateException("appTaskAdapter can't not be null.");
|
|
|
+ }
|
|
|
+ View view = appTaskAdapter.onCreateView(LayoutInflater.from(parent.getContext()), parent);
|
|
|
+ AppTaskItemViewHolder appTaskItemViewHolder = new AppTaskItemViewHolder(view);
|
|
|
+ bindClickListener();
|
|
|
+ return appTaskItemViewHolder;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void bindClickListener() {
|
|
|
+ if (appTaskAdapter == null) {
|
|
|
+ throw new IllegalStateException("appTaskAdapter can't not be null.");
|
|
|
+ }
|
|
|
+ View[] clickViews = appTaskAdapter.getClickViews();
|
|
|
+ if (clickViews == null || clickViews.length == 0) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ View.OnClickListener onClickListener = v -> onAppTaskItemClick((AppTaskDownloadWrapper) v.getTag());
|
|
|
+ for (View clickView : clickViews) {
|
|
|
+ clickView.setOnClickListener(onClickListener);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @SuppressLint("ResourceType")
|
|
|
+ @Override
|
|
|
+ public void onBindViewHolder(@NonNull AppTaskItemViewHolder holder, int position) {
|
|
|
+ if (appTaskAdapter == null) {
|
|
|
+ throw new IllegalStateException("appTaskAdapter can't not be null.");
|
|
|
+ }
|
|
|
+ AppTaskDownloadWrapper appTaskDownloadWrapper = asyncListDiffer.getCurrentList().get(position);
|
|
|
+ // download status
|
|
|
+ appTaskAdapter.onDownloadStatusChanged(appTaskDownloadWrapper.isDownloading());
|
|
|
+ // app name
|
|
|
+ appTaskAdapter.onRenderAppName(appTaskDownloadWrapper, appTaskDownloadWrapper.getAppName());
|
|
|
+ // app icon
|
|
|
+ appTaskAdapter.onRenderAppIcon(appTaskDownloadWrapper, appTaskDownloadWrapper.getAppIcon());
|
|
|
+ // click view
|
|
|
+ setTag2ClickViews(appTaskDownloadWrapper);
|
|
|
+ // task status
|
|
|
+ appTaskAdapter.onRenderTaskStatus(appTaskDownloadWrapper, appTaskDownloadWrapper.getTaskStatus());
|
|
|
+ // download progress
|
|
|
+ appTaskAdapter.onRenderDownloadProgress(appTaskDownloadWrapper.getTotal(), appTaskDownloadWrapper.getProgress());
|
|
|
+ }
|
|
|
+
|
|
|
+ private void setTag2ClickViews(AppTaskDownloadWrapper appTaskDownloadWrapper) {
|
|
|
+ if (appTaskAdapter == null) {
|
|
|
+ throw new IllegalStateException("appTaskAdapter can't not be null.");
|
|
|
+ }
|
|
|
+ View[] clickViews = appTaskAdapter.getClickViews();
|
|
|
+ if (clickViews != null && clickViews.length > 0) {
|
|
|
+ for (View clickView : clickViews) {
|
|
|
+ clickView.setTag(appTaskDownloadWrapper);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onBindViewHolder(@NonNull AppTaskItemViewHolder holder, int position, @NonNull List<Object> payloads) {
|
|
|
+ if (appTaskAdapter == null) {
|
|
|
+ throw new IllegalStateException("appTaskAdapter can't not be null.");
|
|
|
+ }
|
|
|
+ AppTaskDownloadWrapper appTaskDownloadWrapper = asyncListDiffer.getCurrentList().get(position);
|
|
|
+ setTag2ClickViews(appTaskDownloadWrapper);
|
|
|
+ if (payloads.size() == 0) {
|
|
|
+ onBindViewHolder(holder, position);
|
|
|
+ } else {
|
|
|
+ for (Object payload : payloads) {
|
|
|
+ Bundle bundle = (Bundle) payload;
|
|
|
+ for (String key : bundle.keySet()) {
|
|
|
+ switch (key) {
|
|
|
+ case "payload_app_name":
|
|
|
+ appTaskAdapter.onRenderAppName(appTaskDownloadWrapper, bundle.getString(key));
|
|
|
+ break;
|
|
|
+ case "payload_task_status":
|
|
|
+ appTaskAdapter.onRenderTaskStatus(appTaskDownloadWrapper, bundle.getInt(key));
|
|
|
+ break;
|
|
|
+ case "payload_downloading":
|
|
|
+ appTaskAdapter.onDownloadStatusChanged(bundle.getBoolean(key));
|
|
|
+ break;
|
|
|
+ case "payload_progress":
|
|
|
+ case "payload_total":
|
|
|
+ if (bundle.get("payload_progress") == null || bundle.get("payload_total") == null) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ appTaskAdapter.onRenderDownloadProgress(bundle.getLong("payload_total"), bundle.getLong("payload_progress"));
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int getItemCount() {
|
|
|
+ return asyncListDiffer.getCurrentList().size();
|
|
|
+ }
|
|
|
+
|
|
|
+ private void onAppTaskItemClick(AppTaskDownloadWrapper appTaskDownloadWrapper) {
|
|
|
+ if (appTaskDownloadWrapper == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ switch (appTaskDownloadWrapper.getTaskStatus()) {
|
|
|
+ case AppTaskBean.AppTaskStatus.Initial:
|
|
|
+ Log.d(TAG, "onAppTaskItemClick: toInstall.");
|
|
|
+ toInstall(appTaskDownloadWrapper);
|
|
|
+ break;
|
|
|
+ case AppTaskBean.AppTaskStatus.Installed:
|
|
|
+ toOpen(appTaskDownloadWrapper);
|
|
|
+ Log.d(TAG, "onAppTaskItemClick: toOpen.");
|
|
|
+ break;
|
|
|
+ case AppTaskBean.AppTaskStatus.Opened:
|
|
|
+ if (onItemActionCallback != null) {
|
|
|
+ onItemActionCallback.getReward(appTaskDownloadWrapper);
|
|
|
+ }
|
|
|
+ Log.d(TAG, "onAppTaskItemClick: getReward.");
|
|
|
+ break;
|
|
|
+ case AppTaskBean.AppTaskStatus.Finish:
|
|
|
+ //ignore
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (onItemActionCallback != null) {
|
|
|
+ onItemActionCallback.onClick(appTaskDownloadWrapper);
|
|
|
+ }
|
|
|
+ reportClickEvent(appTaskDownloadWrapper);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void reportClickEvent(AppTaskBean appTaskBean) {
|
|
|
+ switch (appTaskBean.getTaskStatus()) {
|
|
|
+ case AppTaskBean.AppTaskStatus.Finish:
|
|
|
+ break;
|
|
|
+ case AppTaskBean.AppTaskStatus.Initial:
|
|
|
+ case AppTaskBean.AppTaskStatus.Installed:
|
|
|
+ AppTaskEvent.report(AppTaskEvent.ATE_CLICK_ITEM_INITIAL);
|
|
|
+ break;
|
|
|
+ case AppTaskBean.AppTaskStatus.Opened:
|
|
|
+ AppTaskEvent.report(AppTaskEvent.ATE_CLICK_ITEM_REWARD);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void toOpen(@NonNull AppTaskDownloadWrapper appTaskDownloadWrapper) {
|
|
|
+ String appPkgName = appTaskDownloadWrapper.getAppPkgName();
|
|
|
+ if (AppInfoUtils.isExistPackage(Utils.getContext(), appPkgName)) {
|
|
|
+ AppTaskEvent.report(AppTaskEvent.ATE_LAUNCH);
|
|
|
+ AppInfoUtils.launchApp(appPkgName);
|
|
|
+ if (onItemActionCallback != null) {
|
|
|
+ onItemActionCallback.updateStatus(appTaskDownloadWrapper.getId(), AppTaskBean.AppTaskStatus.Opened);
|
|
|
+ }
|
|
|
+ removeFromCheckList(appTaskDownloadWrapper.getId());
|
|
|
+ Log.d(TAG, "toOpen: app exist, open it.");
|
|
|
+ } else {
|
|
|
+ AppTaskEvent.report(AppTaskEvent.ATE_DOWNLOAD);
|
|
|
+ toDownload(appTaskDownloadWrapper);
|
|
|
+ Log.d(TAG, "toOpen: app not exist, try to download.");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void toInstall(@NonNull AppTaskDownloadWrapper appTaskDownloadWrapper) {
|
|
|
+ // first of all, check local apk file is exists
|
|
|
+ Observable.just(appTaskDownloadWrapper.getAppPkgName())
|
|
|
+ .map(appPackageName -> {
|
|
|
+ // this step is check apk file that download by sdk is exists
|
|
|
+ AdAppInfoData adAppInfoData = LocalData.queryAdAppInfoByPackageName(appPackageName);
|
|
|
+ if (adAppInfoData == null) {
|
|
|
+ return new File("");
|
|
|
+ }
|
|
|
+ String apkPath = adAppInfoData.getApkPath();
|
|
|
+ File file = new File(apkPath);
|
|
|
+ file = file.exists() && file.isFile() ? file : new File("");
|
|
|
+ Log.d(TAG, "toInstall: sdk apk path ==> " + apkPath + ", file available ==> " + (!"".equals(file.getPath())));
|
|
|
+ return file;
|
|
|
+ })
|
|
|
+ .map(apkFile -> {
|
|
|
+ // if sdk download file is exist just use it
|
|
|
+ if ("".equals(apkFile.getPath())) {
|
|
|
+ // if non, this step is check apk file that download by ourself is exists
|
|
|
+ File downloadFile = new File(DIR_PATH, appTaskDownloadWrapper.getId() + ".apk");
|
|
|
+ if (downloadFile.exists() && downloadFile.isFile() && !checkFileOccupy(downloadFile)) {
|
|
|
+ apkFile = downloadFile;
|
|
|
+ }
|
|
|
+ Log.d(TAG, "toInstall: download apk path ==> " + downloadFile.getPath() + ", file available ==> " + (!"".equals(apkFile.getPath())));
|
|
|
+ }
|
|
|
+ if ("".equals(apkFile.getPath())) {
|
|
|
+ throw new Exception("none available apk file");
|
|
|
+ } else {
|
|
|
+ return apkFile;
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .compose(RxSchedulersUtils.observableIO2Main())
|
|
|
+ .subscribe(new Observer<File>() {
|
|
|
+ @Override
|
|
|
+ public void onSubscribe(@atmob.io.reactivex.rxjava3.annotations.NonNull Disposable d) {
|
|
|
+ compositeDisposable.add(d);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onNext(@atmob.io.reactivex.rxjava3.annotations.NonNull File file) {
|
|
|
+ // local file exists, install it
|
|
|
+ InstallFaultToleranceUtils.installApk(Utils.getContext(), file, () -> {
|
|
|
+ AppTaskEvent.report(AppTaskEvent.ATE_DOWNLOAD);
|
|
|
+ toDownload(appTaskDownloadWrapper);
|
|
|
+ Log.d(TAG, "toInstall: apk install failed, try to download");
|
|
|
+ });
|
|
|
+ addToCheckList(appTaskDownloadWrapper);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onError(@atmob.io.reactivex.rxjava3.annotations.NonNull Throwable e) {
|
|
|
+ // local file not exist, try to download
|
|
|
+ AppTaskEvent.report(AppTaskEvent.ATE_DOWNLOAD);
|
|
|
+ toDownload(appTaskDownloadWrapper);
|
|
|
+ Log.d(TAG, "toInstall: None available apk file, try to download, msg ==> " + e.getMessage());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onComplete() {
|
|
|
+ // ignore, this method invoked means local file exists
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ private void toDownload(AppTaskDownloadWrapper appTaskDownloadWrapper) {
|
|
|
+ String fileName = appTaskDownloadWrapper.getId() + ".apk";
|
|
|
+ RetrofitDownloader.download(appTaskDownloadWrapper.getAppLink(), DIR_PATH, fileName, new RetrofitDownloader.ProgressObserver() {
|
|
|
+ @Override
|
|
|
+ public void onStart() {
|
|
|
+ appTaskDownloadWrapper.setDownloading(true);
|
|
|
+ Bundle bundle = new Bundle();
|
|
|
+ bundle.putBoolean("payload_downloading", true);
|
|
|
+ notifyItemChanged(asyncListDiffer.getCurrentList().indexOf(appTaskDownloadWrapper), bundle);
|
|
|
+ Log.d(TAG, "toDownload onStart: download start, task ==> " + appTaskDownloadWrapper);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onProgress(long total, long progress) {
|
|
|
+ appTaskDownloadWrapper.setDownloading(true);
|
|
|
+ appTaskDownloadWrapper.setTotal(total);
|
|
|
+ appTaskDownloadWrapper.setProgress(progress);
|
|
|
+ Bundle bundle = new Bundle();
|
|
|
+ bundle.putBoolean("payload_downloading", true);
|
|
|
+ bundle.putLong("payload_progress", progress);
|
|
|
+ bundle.putLong("payload_total", total);
|
|
|
+ notifyItemChanged(asyncListDiffer.getCurrentList().indexOf(appTaskDownloadWrapper), bundle);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onComplete(File file) {
|
|
|
+ appTaskDownloadWrapper.setDownloading(false);
|
|
|
+ InstallFaultToleranceUtils.installApk(Utils.getContext(), file, null);
|
|
|
+ addToCheckList(appTaskDownloadWrapper);
|
|
|
+ Bundle bundle = new Bundle();
|
|
|
+ bundle.putBoolean("payload_downloading", false);
|
|
|
+ notifyItemChanged(asyncListDiffer.getCurrentList().indexOf(appTaskDownloadWrapper), bundle);
|
|
|
+ Log.d(TAG, "toDownload onComplete: download complete, task ==> " + appTaskDownloadWrapper);
|
|
|
+ AppTaskEvent.report(AppTaskEvent.ATE_DOWNLOAD_SUCCESS);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onError(String message) {
|
|
|
+ appTaskDownloadWrapper.setDownloading(false);
|
|
|
+ Toast.makeText(Utils.getContext(), "下载失败,请重试", Toast.LENGTH_SHORT).show();
|
|
|
+ Bundle bundle = new Bundle();
|
|
|
+ bundle.putBoolean("payload_downloading", false);
|
|
|
+ notifyItemChanged(asyncListDiffer.getCurrentList().indexOf(appTaskDownloadWrapper), bundle);
|
|
|
+ Log.d(TAG, "toDownload onError: download error, msg ==> " + message + ", task ==> " + appTaskDownloadWrapper);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean checkFileOccupy(File downloadFile) {
|
|
|
+ return !downloadFile.renameTo(downloadFile);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void update(ArrayList<AppTaskBean> appTaskBeans) {
|
|
|
+ ArrayList<AppTaskDownloadWrapper> appTaskDownloadWrappers = new ArrayList<>();
|
|
|
+ Observable.fromIterable(appTaskBeans)
|
|
|
+ .filter(appTaskBean -> appTaskBean.getTaskStatus() != AppTaskBean.AppTaskStatus.Finish)
|
|
|
+ .map(AppTaskDownloadWrapper::new)
|
|
|
+ .compose(RxSchedulersUtils.observableIO2Main())
|
|
|
+ .subscribe(new Observer<AppTaskDownloadWrapper>() {
|
|
|
+ @Override
|
|
|
+ public void onSubscribe(@atmob.io.reactivex.rxjava3.annotations.NonNull Disposable d) {
|
|
|
+ compositeDisposable.add(d);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onNext(@atmob.io.reactivex.rxjava3.annotations.NonNull AppTaskDownloadWrapper appTaskDownloadWrapper) {
|
|
|
+ if (RetrofitDownloader.isActiveTaskExist(appTaskDownloadWrapper.getAppLink())) {
|
|
|
+ toDownload(appTaskDownloadWrapper);
|
|
|
+ }
|
|
|
+ appTaskDownloadWrappers.add(appTaskDownloadWrapper);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onError(@atmob.io.reactivex.rxjava3.annotations.NonNull Throwable e) {
|
|
|
+ Log.e(TAG, "onError: AppTaskBean transform to AppTaskDownloadWrapper error", e);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onComplete() {
|
|
|
+ Log.d(TAG, "onComplete: app task list update success, total length ==> " + appTaskDownloadWrappers.size());
|
|
|
+ Collections.reverse(appTaskDownloadWrappers);
|
|
|
+ asyncListDiffer.submitList(appTaskDownloadWrappers);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ public void checkAppExist() {
|
|
|
+ Log.d(TAG, "app resume, start checkAppExist()");
|
|
|
+ Completable.fromAction(() -> {
|
|
|
+ Iterator<Map.Entry<Long, String>> iterator = potentialInstalledList.entrySet().iterator();
|
|
|
+ while (iterator.hasNext()) {
|
|
|
+ Map.Entry<Long, String> next = iterator.next();
|
|
|
+ Long appTaskId = next.getKey();
|
|
|
+ String appTaskPackageName = next.getValue();
|
|
|
+ if (TextUtils.isEmpty(appTaskPackageName)) {
|
|
|
+ iterator.remove();
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ boolean existPackage = AppInfoUtils.isExistPackage(Utils.getContext(), appTaskPackageName);
|
|
|
+ if (existPackage) {
|
|
|
+ if (FORCE_OPEN) {
|
|
|
+ Log.d(TAG, "checkAppExist: app exist, open it. (id ==> " + appTaskId + ", packageName ==> " + appTaskPackageName + ")");
|
|
|
+ AppTaskEvent.report(AppTaskEvent.ATE_CONFIRM_INSTALLED_LAUNCH);
|
|
|
+ AppInfoUtils.launchApp(appTaskPackageName);
|
|
|
+ if (onItemActionCallback != null) {
|
|
|
+ onItemActionCallback.updateStatus(appTaskId, AppTaskBean.AppTaskStatus.Opened);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ Log.d(TAG, "checkAppExist: app exist, just report. (id ==> " + appTaskId + ", packageName ==> " + appTaskPackageName + ")");
|
|
|
+ if (onItemActionCallback != null) {
|
|
|
+ onItemActionCallback.updateStatus(appTaskId, AppTaskBean.AppTaskStatus.Installed);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ iterator.remove();
|
|
|
+ } else {
|
|
|
+ Log.d(TAG, "checkAppExist: app not exist. (id ==> " + appTaskId + ", packageName ==> " + appTaskPackageName + ")");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .subscribeOn(Schedulers.io())
|
|
|
+ .observeOn(Schedulers.io())
|
|
|
+ .subscribe(new CompletableObserver() {
|
|
|
+ @Override
|
|
|
+ public void onSubscribe(@atmob.io.reactivex.rxjava3.annotations.NonNull Disposable d) {
|
|
|
+ compositeDisposable.add(d);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onComplete() {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onError(@atmob.io.reactivex.rxjava3.annotations.NonNull Throwable e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ private void addToCheckList(@Nullable AppTaskBean appTaskBeanGet) {
|
|
|
+ if (appTaskBeanGet == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ potentialInstalledList.put(appTaskBeanGet.getId(), appTaskBeanGet.getAppPkgName());
|
|
|
+ Log.d(TAG, "addToCheckList() called with: appTaskBeanGet = [" + appTaskBeanGet + "]");
|
|
|
+ }
|
|
|
+
|
|
|
+ private void removeFromCheckList(long id) {
|
|
|
+ potentialInstalledList.remove(id);
|
|
|
+ Log.d(TAG, "removeFromCheckList() called with: id = [" + id + "]");
|
|
|
+ }
|
|
|
+
|
|
|
+ public void setOnItemActionCallback(OnItemActionCallback onItemActionCallback) {
|
|
|
+ this.onItemActionCallback = onItemActionCallback;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void release() {
|
|
|
+ RetrofitDownloader.clearAllObserver();
|
|
|
+ appTaskAdapter = null;
|
|
|
+ Log.d(TAG, "release: clear all observer.");
|
|
|
+ }
|
|
|
+
|
|
|
+ public void triggerFirstTask() {
|
|
|
+ for (int i = 0; i < asyncListDiffer.getCurrentList().size(); i++) {
|
|
|
+ AppTaskDownloadWrapper appTaskDownloadWrapper = asyncListDiffer.getCurrentList().get(i);
|
|
|
+ if (appTaskDownloadWrapper == null) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if (appTaskDownloadWrapper.getTaskStatus() != AppTaskBean.AppTaskStatus.Opened && !appTaskDownloadWrapper.isDownloading()) {
|
|
|
+ onAppTaskItemClick(appTaskDownloadWrapper);
|
|
|
+ Log.d(TAG, "triggerFirstTask: task ==> " + appTaskDownloadWrapper);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ Log.d(TAG, "triggerFirstTask: not has available task.");
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 列表内部通过这个类获取item必要组件
|
|
|
+ */
|
|
|
+ public static class AppTaskItemViewHolder extends RecyclerView.ViewHolder {
|
|
|
+
|
|
|
+ public AppTaskItemViewHolder(@NonNull View itemView) {
|
|
|
+ super(itemView);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public static class AppIconConfig {
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 默认图标
|
|
|
+ */
|
|
|
+ @IntegerRes
|
|
|
+ private int placeholderResId;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 图标的圆角 in dip
|
|
|
+ */
|
|
|
+ private int round;
|
|
|
+
|
|
|
+ @SuppressWarnings("ResourceType")
|
|
|
+ public AppIconConfig() {
|
|
|
+ placeholderResId = ResUtils.getRes("atmob_default_icon", "drawable");
|
|
|
+ round = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ public AppIconConfig placeholderResId(int placeholderResId) {
|
|
|
+ this.placeholderResId = placeholderResId;
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+
|
|
|
+ public AppIconConfig round(int round) {
|
|
|
+ this.round = round;
|
|
|
+ return this;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 用于构建积分墙item, see{@link AppTaskItemViewHolder}
|
|
|
+ */
|
|
|
+ public interface ViewHolderCreator {
|
|
|
+ AppTaskItemViewHolder onCreateViewHolder(LayoutInflater layoutInflater, ViewGroup parent);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static class DiffCallback extends DiffUtil.ItemCallback<AppTaskDownloadWrapper> {
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean areItemsTheSame(@NonNull AppTaskDownloadWrapper oldItem, @NonNull AppTaskDownloadWrapper newItem) {
|
|
|
+ if (oldItem.getId() == 0) {
|
|
|
+ return oldItem.getAppPkgName().equals(newItem.getAppPkgName());
|
|
|
+ }
|
|
|
+ return oldItem.getId() == newItem.getId();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean areContentsTheSame(@NonNull AppTaskDownloadWrapper oldItem, @NonNull AppTaskDownloadWrapper newItem) {
|
|
|
+ if (TextUtils.isEmpty(oldItem.getAppName()) || TextUtils.isEmpty(newItem.getAppName()) || !oldItem.getAppName().equals(newItem.getAppName())) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (oldItem.getTaskStatus() != newItem.getTaskStatus()) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (oldItem.isDownloading() != newItem.isDownloading()) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return oldItem.getProgress() == newItem.getProgress() && oldItem.getTotal() == newItem.getTotal();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Nullable
|
|
|
+ @org.jetbrains.annotations.Nullable
|
|
|
+ @Override
|
|
|
+ public Object getChangePayload(@NonNull AppTaskDownloadWrapper oldItem, @NonNull AppTaskDownloadWrapper newItem) {
|
|
|
+ Bundle bundle = new Bundle();
|
|
|
+ if (TextUtils.isEmpty(oldItem.getAppName()) || TextUtils.isEmpty(newItem.getAppName()) || !oldItem.getAppName().equals(newItem.getAppName())) {
|
|
|
+ bundle.putString("payload_app_name", newItem.getAppName());
|
|
|
+ }
|
|
|
+ if (oldItem.getTaskStatus() != newItem.getTaskStatus()) {
|
|
|
+ bundle.putInt("payload_task_status", newItem.getTaskStatus());
|
|
|
+ }
|
|
|
+ if (oldItem.isDownloading() != newItem.isDownloading()) {
|
|
|
+ bundle.putBoolean("payload_downloading", newItem.isDownloading());
|
|
|
+ }
|
|
|
+ if (oldItem.getProgress() != newItem.getProgress() || oldItem.getTotal() != newItem.getTotal()) {
|
|
|
+ bundle.putLong("payload_progress", newItem.getProgress());
|
|
|
+ bundle.putLong("payload_total", newItem.getTotal());
|
|
|
+ }
|
|
|
+ if (bundle.isEmpty()) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ return bundle;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public interface OnItemActionCallback {
|
|
|
+ void onClick(AppTaskBean appTaskBean);
|
|
|
+
|
|
|
+ void updateStatus(long id, int targetStatus);
|
|
|
+
|
|
|
+ void getReward(AppTaskBean appTaskBean);
|
|
|
+ }
|
|
|
+}
|