405 lines
15 KiB
Java
405 lines
15 KiB
Java
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<KcSelectGameViewHolder> {
|
|
|
|
private static int INSTALLED = 0; // 表示已经安装
|
|
private static int UNINSTALLED = 1; // 表示未安装
|
|
|
|
private CheckBox mApkSelectAll;
|
|
private TextView mApkDeleteBtn;
|
|
|
|
private OnScanListener mScanListener;
|
|
|
|
private List<String> mApkPath;
|
|
private List<InstallGameEntity> mApkList;
|
|
private ArrayMap<Integer, Boolean> 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<Object>() {
|
|
@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<PackageInfo> 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<InstallGameEntity> getApkList() {
|
|
return mApkList;
|
|
}
|
|
|
|
public ArrayMap<Integer, Boolean> getSelectPosition() {
|
|
return mSelectPosition;
|
|
}
|
|
|
|
public void setSelectPosition(ArrayMap<Integer, Boolean> selectPosition) {
|
|
this.mSelectPosition = selectPosition;
|
|
}
|
|
|
|
public void isStopScan() {
|
|
this.mIsStopScan = true;
|
|
}
|
|
|
|
public void deleteApk(int position) {
|
|
mApkList.remove(position);
|
|
|
|
Iterator<Map.Entry<Integer, Boolean>> iterator = mSelectPosition.entrySet().iterator();
|
|
while (iterator.hasNext()) {
|
|
Map.Entry<Integer, Boolean> entry = iterator.next();
|
|
Integer key = entry.getKey();
|
|
|
|
if (key == position) {
|
|
iterator.remove();
|
|
}
|
|
}
|
|
|
|
ArrayMap<Integer, Boolean> 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();
|
|
}
|
|
|
|
}
|