package com.gh.gamecenter.adapter; import android.content.ActivityNotFoundException; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Environment; import android.view.View; import android.view.ViewGroup; import android.widget.CheckBox; import android.widget.RelativeLayout; import android.widget.TextView; import androidx.collection.ArrayMap; import androidx.core.content.ContextCompat; import com.gh.common.util.PackageHelper; import com.gh.common.util.PackageInstaller; import com.gh.common.util.PackageUtils; import com.gh.gamecenter.R; import com.gh.gamecenter.adapter.viewholder.KcSelectGameViewHolder; import com.gh.gamecenter.common.retrofit.Response; import com.gh.gamecenter.common.utils.BitmapUtils; import com.gh.gamecenter.core.utils.MtaHelper; import com.gh.gamecenter.core.utils.TimeUtils; import com.gh.gamecenter.core.utils.ToastUtils; import com.gh.gamecenter.databinding.KcGameSelectItemBinding; import com.gh.gamecenter.feature.entity.InstallGameEntity; import com.lightgame.adapter.BaseRecyclerAdapter; import com.lightgame.utils.RuntimeUtils; import java.io.File; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import io.reactivex.Observable; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.schedulers.Schedulers; /** * Created by khy on 2017/1/24. */ public class CleanApkAdapter extends BaseRecyclerAdapter { private static int INSTALLED = 0; // 表示已经安装 private static int UNINSTALLED = 1; // 表示未安装 private CheckBox mApkSelectAll; private TextView mApkDeleteBtn; private OnScanListener mScanListener; private List mApkPath; private List mApkList; private ArrayMap mSelectPosition; private boolean mIsStopScan; private boolean mIsScanOver; private boolean mIsChooseApk; public CleanApkAdapter(Context context, OnScanListener listener, TextView apkDeleteBtn, CheckBox apkSelectAll, boolean isChooseApk) { super(context); mApkDeleteBtn = apkDeleteBtn; mApkSelectAll = apkSelectAll; mIsChooseApk = isChooseApk; mScanListener = listener; mApkList = new ArrayList<>(); mSelectPosition = new ArrayMap<>(); mApkPath = new ArrayList<>(); mIsStopScan = false; mIsScanOver = false; init(); } private void init() { Observable.create(emitter -> { // 扫描和获取apk数据 分步操作 尽量避免 StackoverflowError FindAllAPKPath(Environment.getExternalStorageDirectory()); FindAllAPKPath(mContext.getFilesDir()); LoadApkData(); emitter.onComplete(); }) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Response() { @Override public void onComplete() { super.onComplete(); mIsScanOver = true; mScanListener.onScanOver(); if (mApkList.size() == 0) { mScanListener.noData(); } notifyItemRangeChanged(0, getItemCount()); } }); } /** * 根据apk文件路径检查可用的apk和获取apk数据 */ private void LoadApkData() { for (String apk_path : mApkPath) { InstallGameEntity apkEntity = new InstallGameEntity(); PackageManager pm = mContext.getApplicationContext().getPackageManager(); PackageInfo packageInfo = pm.getPackageArchiveInfo(apk_path, 0); if (packageInfo == null) continue; ApplicationInfo appInfo = packageInfo.applicationInfo; /**获取apk的图标 */ appInfo.sourceDir = apk_path; appInfo.publicSourceDir = apk_path; Drawable apk_icon = appInfo.loadIcon(pm); Bitmap originalBitmap = BitmapUtils.drawableToBitmap(apk_icon, true); apkEntity.setGameBm(BitmapUtils.compressBitmap(originalBitmap, 100)); /** apk的绝对路劲 */ apkEntity.setGamePath(apk_path); /** apk的版本名称 String */ String versionName = packageInfo.versionName; apkEntity.setGameVersion(versionName); String apkName = packageInfo.applicationInfo.loadLabel(pm).toString(); apkEntity.setGameName(apkName); File file = new File(apk_path); apkEntity.setGameSize(file.length()); apkEntity.setLastUpdateTime(file.lastModified()); apkEntity.setPackageName(PackageUtils.getPackageNameByPath(mContext, apk_path)); apkEntity.setVersionCode(packageInfo.versionCode); if (apkEntity.getGamePath() != null && apkEntity.getGamePath().length() > 0) { int dot = apkEntity.getGamePath().lastIndexOf('.'); if ((dot > -1) && (dot < apkEntity.getGamePath().length() - 1)) { apkEntity.setFormat(apkEntity.getGamePath().substring(dot + 1)); } } /**安装处理类型*/ /** 得到包名 */ String packageName = packageInfo.packageName; int type = doType(packageName); apkEntity.setInstallStatus(type); mApkList.add(apkEntity); mSelectPosition.put((mApkList.size() - 1), false); RuntimeUtils.getInstance().runOnUiThread(() -> notifyItemChanged((mApkList.size() - 1))); } } /** * 扫描内存卡 获取apk文件路径 * * @param file 文件路径 */ public void FindAllAPKPath(File file) { if (mIsStopScan) { return; } if (file.isFile()) { // Utils.log("===== 是文件" + file.getAbsolutePath().toString()); String name_s = file.getName(); String apk_path; if (name_s.toLowerCase().endsWith(".apk")) { apk_path = file.getAbsolutePath();// apk文件的绝对路劲 mApkPath.add(apk_path); } } else { // Utils.log("===== 是文件夹" + file.getAbsolutePath().toString()); File[] files = file.listFiles(); if (files != null && files.length > 0) { for (File file_str : files) { FindAllAPKPath(file_str); } } } } private int doType(String packageName) { List pakageinfos = PackageHelper.INSTANCE.getInstalledPackages(mContext, 0); for (PackageInfo pi : pakageinfos) { if ((pi.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) { String pi_packageName = pi.packageName; //如果这个包名在系统已经安装过的应用中存在 if (packageName.endsWith(pi_packageName)) { return INSTALLED; } } } return UNINSTALLED; } @Override public KcSelectGameViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { return new KcSelectGameViewHolder(KcGameSelectItemBinding.inflate(mLayoutInflater, parent, false)); } @Override public void onBindViewHolder(final KcSelectGameViewHolder holder, int position) { final InstallGameEntity gameEntity = mApkList.get(position); double size = (((float) gameEntity.getGameSize() / 1024) / 1024); DecimalFormat df = new DecimalFormat("#.00"); String sizeName = df.format(size) + "MB"; View itemView = holder.itemView; Drawable background = ContextCompat.getDrawable(itemView.getContext(), R.drawable.reuse_listview_item_style); itemView.setBackground(background); holder.binding.selectGameCbRl.setVisibility(View.VISIBLE); holder.binding.selectGameBtn.setVisibility(View.VISIBLE); if (mSelectPosition.get(position)) { holder.binding.selectGameBtn.setChecked(true); } else { holder.binding.selectGameBtn.setChecked(false); } holder.binding.selectGameNameAndsize.setText(gameEntity.getGameName()); holder.binding.selectGameThumb.setImageBitmap(gameEntity.getGameBm()); if (!mIsChooseApk) { if (gameEntity.getInstallStatus() == INSTALLED) { holder.binding.selectGameSize.setText(R.string.installed); holder.binding.selectGameSize.setTextColor(ContextCompat.getColor(mContext, R.color.text_theme)); } else { holder.binding.selectGameSize.setText(R.string.installed_not); holder.binding.selectGameSize.setTextColor(ContextCompat.getColor(mContext, R.color.secondary_red)); } holder.binding.selectGameDes.setText(mContext.getString(R.string.clean_apk_version, gameEntity.getGameVersion(), sizeName)); holder.binding.selectGameDes.setTextColor(ContextCompat.getColor(mContext, R.color.content)); } else { holder.binding.selectGameSize.setVisibility(View.GONE); RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) holder.binding.selectGameDes.getLayoutParams(); params.bottomMargin = 0; params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM); holder.binding.selectGameDes.setLayoutParams(params); String des = TimeUtils.getFormatTime(gameEntity.getLastUpdateTime(), "yyyy-MM-dd HH:mm") + " " + sizeName; holder.binding.selectGameDes.setText(des); } if (mIsScanOver) { holder.binding.selectGameBtn.setEnabled(true); } else { holder.binding.selectGameBtn.setEnabled(false); } holder.binding.selectGameCbRl.setOnClickListener(v -> { if (!mIsChooseApk) { if (mSelectPosition.get(holder.getAdapterPosition())) { checkBoxControl(false, holder.getAdapterPosition()); holder.binding.selectGameBtn.setChecked(false); } else { checkBoxControl(true, holder.getAdapterPosition()); holder.binding.selectGameBtn.setChecked(true); } } else { singleChoose(position); } }); holder.binding.selectGameBtn.setOnClickListener(v -> { if (!mIsChooseApk) { if (mSelectPosition.get(holder.getAdapterPosition())) { checkBoxControl(false, holder.getAdapterPosition()); holder.binding.selectGameBtn.setChecked(false); MtaHelper.onEvent("我的光环_设置", "安装包清理", "取消选中"); } else { checkBoxControl(true, holder.getAdapterPosition()); holder.binding.selectGameBtn.setChecked(true); MtaHelper.onEvent("我的光环_设置", "安装包清理", "选中"); } } else { singleChoose(position); } }); holder.itemView.setOnClickListener(v -> { if (mIsChooseApk) { singleChoose(position); } else { if (mIsScanOver) { try { mContext.startActivity(PackageInstaller.getInstallIntent(mContext, gameEntity.getGamePath())); } catch (ActivityNotFoundException e) { ToastUtils.toast("找不到 APK 安装器,请稍后再试"); } } } }); } public void checkBoxControl(boolean isChecked, int position) { if (isChecked) { mSelectPosition.put(position, true); } else { mSelectPosition.put(position, false); } long gameSize = 0; int i = 0; if (mApkList.size() == 0) return; for (Integer integer : mSelectPosition.keySet()) { if (mSelectPosition.get(integer)) { gameSize = gameSize + mApkList.get(integer).getGameSize(); i++; } } if (i == mApkList.size()) { mApkSelectAll.setChecked(true); } else { mApkSelectAll.setChecked(false); } if (gameSize == 0) { mApkDeleteBtn.setText("一键删除"); } else { double size = (((float) gameSize / 1024) / 1024); DecimalFormat df = new DecimalFormat("0.00"); String sizeName = df.format(size) + "MB"; mApkDeleteBtn.setText(mContext.getString(R.string.clean_apk_deleteall, i, sizeName)); } } public void singleChoose(int position) { for (Integer integer : mSelectPosition.keySet()) { mSelectPosition.put(integer, false); } mSelectPosition.put(position, true); notifyDataSetChanged(); } @Override public int getItemCount() { return mApkList.size(); } public List getApkList() { return mApkList; } public ArrayMap getSelectPosition() { return mSelectPosition; } public void setSelectPosition(ArrayMap selectPosition) { this.mSelectPosition = selectPosition; } public void isStopScan() { this.mIsStopScan = true; } public void deleteApk(int position) { mApkList.remove(position); Iterator> iterator = mSelectPosition.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry entry = iterator.next(); Integer key = entry.getKey(); if (key == position) { iterator.remove(); } } ArrayMap newMap = new ArrayMap<>(mSelectPosition); for (Integer integer : newMap.keySet()) { if (integer > position) { int newPosition = integer - 1; mSelectPosition.put(newPosition, mSelectPosition.get(integer)); } } if (mSelectPosition.size() > mApkList.size()) { mSelectPosition.removeAt(mSelectPosition.size() - 1); } notifyItemRemoved(position); } public interface OnScanListener { void onScanOver(); void noData(); } }