Files
VscoolOS/app/src/main/java/com/xxpatx/os/utils/ApkUtils.java
tongtongstudio b5b12c3e83 version:1.2.9
fix:修复没有微信时打开报错
update:新增单独联系人页面
2024-10-14 09:42:27 +08:00

1023 lines
42 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package com.xxpatx.os.utils;
import android.app.ActivityManager;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.graphics.drawable.Drawable;
import android.os.Binder;
import android.os.Build;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
import androidx.annotation.RequiresApi;
import com.arialyy.aria.core.Aria;
import com.hjq.toast.Toaster;
import com.tencent.mmkv.MMKV;
import com.xxpatx.os.BuildConfig;
import com.xxpatx.os.R;
import com.xxpatx.os.activity.quickapp.QuickAppActivity;
import com.xxpatx.os.bean.AppInfo;
import com.xxpatx.os.bean.DesktopIcon;
import com.xxpatx.os.config.CommonConfig;
import com.xxpatx.os.gson.GsonUtils;
import com.xxpatx.os.manager.AppManager;
import com.xxpatx.os.manager.AppStatusManager;
import com.xxpatx.os.receiver.InstallResultReceiver;
import com.xxpatx.os.shortcut.ShortcutPkgInfo;
import com.xxpatx.os.shortcut.ShortcutUtils;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.core.ObservableEmitter;
import io.reactivex.rxjava3.core.ObservableOnSubscribe;
import io.reactivex.rxjava3.core.Observer;
import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.rxjava3.schedulers.Schedulers;
public class ApkUtils {
public static HashSet<String> excludePackageName = new HashSet<String>() {{
this.add(BuildConfig.APPLICATION_ID);
this.add("org.chromium.browser");
this.add("com.sprd.sprdnote");
this.add("com.android.deskclock");
this.add("com.alldocube.store");
this.add("com.android.email");
this.add("com.android.calendar");
this.add("com.android.uiuios");
this.add("com.uiui.os");
this.add("com.uiui.aios");
this.add("com.uiui.videoplayer");
// this.add("com.uiui.health");
this.add("com.tencent.android.qqdownloader");
// this.add("com.xxpatx.store");
this.add("com.joytv.live");
this.add("com.xxpatx.store");
this.add("com.teclast.zyos");
this.add("com.teclast.zy");
this.add("com.teclast.zyappstore");
this.add("com.teclast.zybrowser");
}};
public static HashSet<String> excludeClassName = new HashSet<String>() {{
this.add("com.android.dialer.app.calllog.CallLogActivity");
}};
public static HashSet<String> showPackageName = new HashSet<String>() {{
this.add("com.xxpatx.sn");
this.add("com.uiuios.browser");
// this.add("com.xxpatx.store");
this.add("com.android.dialer");
this.add("com.android.gallery3d");
this.add("com.android.settings");
this.add("com.android.messaging");
this.add("com.android.camera2");
this.add("com.mediatek.camera");
this.add("com.android.mms");
this.add("com.uiui.city");
this.add("com.uiui.health");
// this.add("com.alldocube.store");
// this.add("com.android.fmradio");
// this.add("com.android.documentsui");
// this.add("com.android.calculator2");
}};
private static HashSet<String> allHintPackage = new HashSet<String>() {{
this.add("com.android.uiuios");
}};
private static final String TAG = "ApkUtils";
public static ArrayList<ApplicationInfo> getSystemApp(Context context) {
PackageManager pm = context.getPackageManager();
// 查询所有已经安装的应用程序
List<ApplicationInfo> appInfos = pm.getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES);// GET_UNINSTALLED_PACKAGES代表已删除但还有安装目录的
ArrayList<ApplicationInfo> applicationInfos = new ArrayList<>();
// 创建一个类别为CATEGORY_LAUNCHER的该包名的Intent
Intent resolveIntent = new Intent(Intent.ACTION_MAIN, null);
resolveIntent.addCategory(Intent.CATEGORY_LAUNCHER);
// 通过getPackageManager()的queryIntentActivities方法遍历,得到所有能打开的app的packageName
List<ResolveInfo> resolveinfoList = pm.queryIntentActivities(resolveIntent, 0);
Set<String> allowPackages = new HashSet();
for (ResolveInfo resolveInfo : resolveinfoList) {
Log.i(TAG, "queryFilterAppInfo: " + resolveInfo.activityInfo.packageName);
allowPackages.add(resolveInfo.activityInfo.packageName);
}
for (ApplicationInfo app : appInfos) {
if (allHintPackage.contains(app.packageName)) continue;
if ((app.flags & ApplicationInfo.FLAG_SYSTEM) > 0) {
if (allowPackages.contains(app.packageName)
&& !showPackageName.contains(app.packageName)) {
applicationInfos.add(app);
Log.e(TAG, "getSystemApp: " + app.packageName);
}
}
}
applicationInfos.sort(new Comparator<ApplicationInfo>() {
@Override
public int compare(ApplicationInfo o1, ApplicationInfo o2) {
return Collator.getInstance(Locale.CHINESE).compare(o1.loadLabel(pm).toString(), o2.loadLabel(pm).toString());
// return o1.loadLabel(pm).toString().compareTo(o2.loadLabel(pm).toString());
}
});
applicationInfos.sort(new Comparator<ApplicationInfo>() {
@Override
public int compare(ApplicationInfo o1, ApplicationInfo o2) {
if ((o1.flags & ApplicationInfo.FLAG_SYSTEM) <= (o2.flags & ApplicationInfo.FLAG_SYSTEM)) {
return 1;
} else {
return -1;
}
}
});
return applicationInfos;
}
private static List<String> defaultSort = new ArrayList<String>() {{
this.add("com.android.dialer");
this.add("com.android.messaging");
this.add("com.android.gallery3d");
this.add("com.android.camera2");
this.add("com.android.settings");
this.add("com.xxpatx.sn");
this.add("com.xxpatx.store");
}};
private static List<String> hideApp = new ArrayList<String>() {{
this.add("com.xxpatx.sn");
this.add("com.xxpatx.os");
this.add("com.xxpatx.store");
this.add("com.android.quicksearchbox");
this.add("com.android.stk");
this.add("com.debug.loggerui");
this.add("com.mediatek.gnss.nonframeworklbs");
this.add("com.tencent.mm");
this.add("com.ss.android.ugc.aweme");
this.add("com.mediatek.camera");
this.add("cn.etouch.ecalendar");
}};
/**
* @param context
* @return
*/
public static ArrayList<DesktopIcon> queryFilterAppInfo(Context context) {
MMKV mmkv = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE);
String quickAppString = Settings.Global.getString(context.getContentResolver(), QuickAppActivity.QUICK_APP_KEY);
List<String> quickApps;
if (TextUtils.isEmpty(quickAppString)) {
quickApps = new ArrayList<>();
} else {
List<String> split = new ArrayList<>(Arrays.asList(quickAppString.split(",")));
quickApps = split.stream().filter(s -> ApkUtils.isAvailable(context, s)).collect(Collectors.toList());
}
PackageManager pm = context.getPackageManager();
// 查询所有已经安装的应用程序
List<ResolveInfo> resolveInfos = new ArrayList<>();
// 创建一个类别为CATEGORY_LAUNCHER的该包名的Intent
Intent resolveIntent = new Intent(Intent.ACTION_MAIN, null);
resolveIntent.addCategory(Intent.CATEGORY_LAUNCHER);
// 通过getPackageManager()的queryIntentActivities方法遍历,得到所有能打开的app的packageName
List<ResolveInfo> resolveinfoList = pm.queryIntentActivities(resolveIntent, 0);
Set<String> allowPackages = new HashSet();
for (ResolveInfo resolveInfo : resolveinfoList) {
Log.i(TAG, "queryFilterAppInfo: " + resolveInfo.activityInfo.packageName);
Log.i(TAG, "queryFilterAppInfo class: " + resolveInfo.activityInfo.name);
allowPackages.add(resolveInfo.activityInfo.packageName);
}
String pkgString = Settings.Global.getString(context.getContentResolver(), CommonConfig.UIUI_APPSTORE_PACKAGE_LIST);
Set<String> pkgSet;
if (TextUtils.isEmpty(pkgString)) {
pkgSet = new ArraySet<>();
} else {
pkgSet = new HashSet<>(new ArrayList<>(Arrays.asList(pkgString.split(","))));
}
Log.e(TAG, "queryFilterAppInfo: pkgSet = " + pkgSet);
int frist = mmkv.decodeInt(CommonConfig.UIUI_FIRST_OPEN, 0);
for (ResolveInfo resolveInfo : resolveinfoList) {
String pkg = resolveInfo.activityInfo.packageName;
if (hideApp.contains(pkg)) {
Log.e(TAG, "queryFilterAppInfo: hideApp = " + pkg);
continue;
}
if (quickApps.contains(pkg)) {
Log.e(TAG, "queryFilterAppInfo: quickApps = " + pkg);
continue;
}
if (appIsDisable(context, pkg)) {
Log.e(TAG, "queryFilterAppInfo: disable = " + pkg);
continue;
}
if (AppStatusManager.getInstance().getHidedAppSet().contains(pkg)) {
Log.e(TAG, "queryFilterAppInfo: hided = " + pkg);
continue;
}
if (AppManager.getInstance().getAddDesktopIconSet().contains(pkg)) {
Log.e(TAG, "queryFilterAppInfo: quick = " + pkg);
continue;
}
if (isSystemApp(context, pkg))//通过flag排除系统应用会将电话、短信也排除掉
{
if (showPackageName.contains(pkg)) {
resolveInfos.add(resolveInfo);
}
} else {
if (frist == 0) {
if (pkgSet.contains(pkg)) {
if (allowPackages.contains(pkg) && !excludePackageName.contains(pkg)) {
resolveInfos.add(resolveInfo);
}
} else {
if ("com.xxpatx.sn".equals(pkg)) {
resolveInfos.add(resolveInfo);
} else {
Log.e(TAG, "queryFilterAppInfo: pkgSet ! contains " + pkg);
AppStatusManager.getInstance().addHidedApp(pkg);
}
}
} else {
if (allowPackages.contains(pkg) && !excludePackageName.contains(pkg)) {
resolveInfos.add(resolveInfo);
}
}
}
}
if (Settings.Global.getInt(context.getContentResolver(), "is_activity", 0) == 0) {
resolveInfos.removeIf(resolveInfo -> "com.uiui.city".equals(resolveInfo.activityInfo.packageName));
// resolveInfos.removeIf(applicationInfo -> "com.uiui.sn".equals(applicationInfo.packageName));
}
List<ResolveInfo> sort1 = resolveInfos.stream().sorted(new Comparator<ResolveInfo>() {
@Override
public int compare(ResolveInfo o1, ResolveInfo o2) {
return Collator.getInstance(Locale.CHINESE).compare(o1.loadLabel(pm).toString(), o2.loadLabel(pm).toString());
// return o1.loadLabel(pm).toString().compareTo(o2.loadLabel(pm).toString());
}
}).collect(Collectors.toList());
List<ResolveInfo> sort2 = sort1.stream().sorted(new Comparator<ResolveInfo>() {
@Override
public int compare(ResolveInfo o1, ResolveInfo o2) {
try {
if ((pm.getApplicationInfo(o1.activityInfo.packageName, 0).flags & ApplicationInfo.FLAG_SYSTEM) < (pm.getApplicationInfo(o2.activityInfo.packageName, 0).flags & ApplicationInfo.FLAG_SYSTEM)) {
return 1;
} else {
return -1;
}
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return 0;
}
}).collect(Collectors.toList());
ArrayList<DesktopIcon> desktopIcons = new ArrayList<>();
for (ResolveInfo applicationInfo : sort2) {
if (!excludeClassName.contains(applicationInfo.activityInfo.name)) {
desktopIcons.add(DesktopIcon.creatDesktopIcon(context, applicationInfo));
}
}
List<ShortcutPkgInfo> shortcutPkgInfos = ShortcutUtils.getInstance().getShortcutList();
desktopIcons.addAll(shortcutPkgInfos);
// DesktopIcon dailyIcon = new DesktopIcon();
//// dailyIcon.setIcon(context.getDrawable(R.drawable.icon_daily_app));
// dailyIcon.setTitle("日常应用");
// dailyIcon.setPackage("aios.daily.app");
// desktopIcons.add(0, dailyIcon);
// DesktopIcon familyIcon = new DesktopIcon();
//// familyIcon.setIcon(context.getDrawable(R.drawable.com_android_appstore));
// familyIcon.setTitle("应用市场");
// familyIcon.setPackage("aios.appstore");
// desktopIcons.add(0, familyIcon);
// DesktopIcon exitIcon = new DesktopIcon();
// exitIcon.setIcon(context.getDrawable(R.drawable.exit_icon));
// exitIcon.setTitle("切换系统");
// exitIcon.setPackage("aios.exit");
// desktopIcons.add(exitIcon);
mmkv.encode(CommonConfig.UIUI_FIRST_OPEN, 1);
return desktopIcons;
}
public static final HashSet<String> phoneShowPackageName = new HashSet<String>() {{
this.add("com.xxpatx.sn");
// this.add("com.uiuios.browser");
// this.add("com.android.dialer");
// this.add("com.android.gallery3d");
// this.add("com.android.settings");
// this.add("com.android.messaging");
// this.add("com.android.camera2");
// this.add("com.mediatek.camera");
// this.add("com.android.mms");
// this.add("com.uiui.city");
// this.add("com.uiui.health");
}};
public static ArrayList<DesktopIcon> getAppstoreAppInfo(Context context) {
MMKV mmkv = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE);
PackageManager pm = context.getPackageManager();
// 查询所有已经安装的应用程序
List<ResolveInfo> resolveInfos = new ArrayList<>();
// 创建一个类别为CATEGORY_LAUNCHER的该包名的Intent
Intent resolveIntent = new Intent(Intent.ACTION_MAIN, null);
resolveIntent.addCategory(Intent.CATEGORY_LAUNCHER);
// 通过getPackageManager()的queryIntentActivities方法遍历,得到所有能打开的app的packageName
List<ResolveInfo> resolveinfoList = pm.queryIntentActivities(resolveIntent, 0);
Set<String> allPackages = new HashSet();
for (ResolveInfo resolveInfo : resolveinfoList) {
Log.i(TAG, "getAppstoreAppInfo: " + resolveInfo.activityInfo.packageName);
Log.i(TAG, "getAppstoreAppInfo class: " + resolveInfo.activityInfo.name);
allPackages.add(resolveInfo.activityInfo.packageName);
}
String pkgString = Settings.Global.getString(context.getContentResolver(), CommonConfig.UIUI_APPSTORE_PACKAGE_LIST);
Set<String> pkgSet;
if (TextUtils.isEmpty(pkgString)) {
pkgSet = new ArraySet<>();
} else {
pkgSet = new HashSet<>(new ArrayList<>(Arrays.asList(pkgString.split(","))));
}
Log.e(TAG, "getAppstoreAppInfo: pkgSet = " + pkgSet);
int frist = mmkv.decodeInt(CommonConfig.UIUI_FIRST_OPEN, 0);
for (ResolveInfo resolveInfo : resolveinfoList) {
String pkg = resolveInfo.activityInfo.packageName;
if (AppStatusManager.getInstance().getHidedAppSet().contains(pkg)) {
Log.e(TAG, "getAppstoreAppInfo: hided = " + pkg);
continue;
}
if (hideApp.contains(pkg)) {
Log.e(TAG, "getAppstoreAppInfo: hideApp = " + pkg);
continue;
}
if (frist == 0) {
if (pkgSet.contains(pkg)) {
if (allPackages.contains(pkg) && !excludePackageName.contains(pkg)) {
resolveInfos.add(resolveInfo);
}
} else {
if ("com.android.mms".equals(pkg)) {
resolveInfos.add(resolveInfo);
} else {
Log.e(TAG, "getAppstoreAppInfo: pkgSet ! contains " + pkg);
AppStatusManager.getInstance().addHidedApp(pkg);
}
}
} else {
if (allPackages.contains(pkg) && !excludePackageName.contains(pkg)) {
resolveInfos.add(resolveInfo);
}
}
}
List<ResolveInfo> sort1 = resolveInfos.stream().sorted(new Comparator<ResolveInfo>() {
@Override
public int compare(ResolveInfo o1, ResolveInfo o2) {
return Collator.getInstance(Locale.CHINESE).compare(o1.loadLabel(pm).toString(), o2.loadLabel(pm).toString());
}
}).collect(Collectors.toList());
List<ResolveInfo> sort2 = sort1.stream().sorted(new Comparator<ResolveInfo>() {
@Override
public int compare(ResolveInfo o1, ResolveInfo o2) {
try {
if ((pm.getApplicationInfo(o1.activityInfo.packageName, 0).flags & ApplicationInfo.FLAG_SYSTEM) < (pm.getApplicationInfo(o2.activityInfo.packageName, 0).flags & ApplicationInfo.FLAG_SYSTEM)) {
return 1;
} else {
return -1;
}
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return 0;
}
}).collect(Collectors.toList());
ArrayList<DesktopIcon> desktopIcons = new ArrayList<>();
for (ResolveInfo applicationInfo : sort2) {
if (!excludeClassName.contains(applicationInfo.activityInfo.name)) {
desktopIcons.add(DesktopIcon.creatDesktopIcon(context, applicationInfo));
}
}
if (!AppStatusManager.getInstance().getHidedAppSet().contains(AppManager.SERVICE_PACKAGE)) {
DesktopIcon dailyIcon = new DesktopIcon();
dailyIcon.setTitle("客服中心");
dailyIcon.setPackage(AppManager.SERVICE_PACKAGE);
desktopIcons.add(0, dailyIcon);
}
if (!AppStatusManager.getInstance().getHidedAppSet().contains(AppManager.CONTACT_PACKAGE)) {
DesktopIcon contactIcon = new DesktopIcon();
contactIcon.setTitle("联系人");
contactIcon.setPackage(AppManager.CONTACT_PACKAGE);
desktopIcons.add(1, contactIcon);
}
List<ShortcutPkgInfo> shortcutPkgInfos = ShortcutUtils.getInstance().getShortcutList();
desktopIcons.addAll(shortcutPkgInfos);
mmkv.encode(CommonConfig.UIUI_FIRST_OPEN, 1);
return desktopIcons;
}
public static boolean isSystemApp(Context context, String pkg) {
PackageManager pm = context.getPackageManager();
ApplicationInfo applicationInfo = null;
try {
applicationInfo = pm.getApplicationInfo(pkg, 0);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
if (applicationInfo == null) return false;
return (applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) > 0;
}
public static boolean appIsDisable(Context context, String pkg) {
PackageManager pm = context.getPackageManager();
return pm.getApplicationEnabledSetting(pkg) == PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
}
public static boolean disableApp(Context context, String pkg) {
PackageManager pm = context.getPackageManager();
try {
pm.setApplicationEnabledSetting(pkg, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 0);
return true;
} catch (Exception e) {
return false;
}
}
/**
* 获取第三方应用
*
* @param context
* @return
*/
public static List<String> queryFilterAppList(Context context) {
PackageManager pm = context.getPackageManager();
// 查询所有已经安装的应用程序
List<ApplicationInfo> appInfos = pm.getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES);// GET_UNINSTALLED_PACKAGES代表已删除但还有安装目录的
List<String> applicationInfos = new ArrayList<>();
for (ApplicationInfo app : appInfos) {
// Log.e("queryFilterAppInfo", String.valueOf(app.flags));
// Log.e("queryFilterAppInfo", String.valueOf((app.flags & mask)));
if ((app.flags & ApplicationInfo.FLAG_SYSTEM) == 1) {
//通过flag排除系统应用会将电话、短信也排除掉
} else {
applicationInfos.add(app.packageName);
Log.e("queryFilterAppInfo", app.packageName);
}
}
return applicationInfos;
}
public static List<String> getRuningPackageList(Context context) {
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> runningAppProcesses = activityManager.getRunningAppProcesses();
Set<String> map = runningAppProcesses.stream().map(new Function<ActivityManager.RunningAppProcessInfo, String>() {
@Override
public String apply(ActivityManager.RunningAppProcessInfo runningAppProcessInfo) {
String processName = runningAppProcessInfo.processName;
String[] split = processName.split(":");
return split[0];
}
}).collect(Collectors.toSet());
map.remove("system");
map.remove("android");
map.remove("com.android.networkstack.process");
map.remove("android.process.media");
map.remove("com.android.dreams.basic");
map.remove("com.android.musicfx");
map.remove("say.whatever");
Set<String> filter = map.stream().filter(new Predicate<String>() {
@Override
public boolean test(String s) {
return !ApkUtils.isSystemApp(context, s);
}
}).collect(Collectors.toSet());
Log.e(TAG, "getRuningPackageList: " + filter);
return new ArrayList<>(filter);
}
public static PackageInfo getPackageInfo(Context context, String pkg) {
PackageManager packageManager = context.getPackageManager();
PackageInfo packageInfo = null;
try {
packageInfo = packageManager.getPackageInfo(pkg, 0);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return packageInfo;
}
public static ApplicationInfo getApplicationInfo(Context context, String pkg) {
PackageManager packageManager = context.getPackageManager();
ApplicationInfo applicationInfo = null;
try {
applicationInfo = packageManager.getApplicationInfo(pkg, 0);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return applicationInfo;
}
public static Drawable getAppDrawable(Context context, String pkg) {
if (context == null) {
return null;
}
Drawable appIcon = context.getDrawable(R.mipmap.ic_launcher);
if (TextUtils.isEmpty(pkg)) {
return appIcon;
}
PackageManager packageManager = context.getPackageManager();
ApplicationInfo applicationInfo = null;
try {
applicationInfo = packageManager.getApplicationInfo(pkg, 0);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
if (applicationInfo != null) {
return applicationInfo.loadIcon(packageManager);
} else {
return appIcon;
}
}
public static void openApp(Context context, String packageName) {
Intent intent = context.getPackageManager().getLaunchIntentForPackage(packageName);
if (intent != null) {
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
}
public static boolean openPackage(Context context, String packageName) {
Context pkgContext = getPackageContext(context, packageName);
Intent intent = getAppOpenIntentByPackageName(context, packageName);
if (pkgContext != null && intent != null) {
pkgContext.startActivity(intent);
return true;
}
Toaster.show("应用未安装");
return false;
}
public static boolean openPackage(Context context, String packageName, String className) {
if (TextUtils.isEmpty(className)) {
return openPackage(context, packageName);
}
ComponentName cn = new ComponentName(packageName, className);
Intent intent = new Intent();
intent.setComponent(cn);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (context != null) {
try {
context.startActivity(intent);
return true;
} catch (Exception e) {
Log.e(TAG, "openPackage: " + e.getMessage());
Toaster.show("应用未安装");
}
}
return false;
}
public static Context getPackageContext(Context context, String packageName) {
Context pkgContext = null;
if (context.getPackageName().equals(packageName)) {
pkgContext = context;
} else {
// 创建第三方应用的上下文环境
try {
pkgContext = context.createPackageContext(packageName,
Context.CONTEXT_IGNORE_SECURITY
| Context.CONTEXT_INCLUDE_CODE);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
}
return pkgContext;
}
public static Intent getAppOpenIntentByPackageName(Context context, String packageName) {
//Activity完整名
String mainAct = null;
//根据包名寻找
PackageManager pkgMag = context.getPackageManager();
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.setFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED | Intent.FLAG_ACTIVITY_NEW_TASK);
List<ResolveInfo> list = pkgMag.queryIntentActivities(intent,
PackageManager.GET_ACTIVITIES);
for (int i = 0; i < list.size(); i++) {
ResolveInfo info = list.get(i);
if (info.activityInfo.packageName.equals(packageName)) {
mainAct = info.activityInfo.name;
break;
}
}
if (TextUtils.isEmpty(mainAct)) {
return null;
}
intent.setComponent(new ComponentName(packageName, mainAct));
return intent;
}
public static String getAPPVersionName(Context context, String packageName) {
String versionName = "0";
if (TextUtils.isEmpty(packageName)) {
return versionName;
}
PackageManager pm = context.getPackageManager();
try {
PackageInfo packageInfo = pm.getPackageInfo(packageName, 0);
versionName = packageInfo.versionName;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return versionName;
}
public static String getAppNameByPackage(Context context, String pkg) {
PackageManager packageManager = context.getPackageManager();
try {
ApplicationInfo applicationInfo = packageManager.getApplicationInfo(pkg, PackageManager.GET_META_DATA);
String packageName = packageManager.getApplicationLabel(applicationInfo).toString();
return packageName;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return "";
}
/**
* 检查手机上是否安装了指定的软件
*/
public static boolean isAvailable(Context context, String packageName) {
PackageManager packageManager = context.getPackageManager();
PackageInfo info = null;
try {
info = packageManager.getPackageInfo(packageName, 0);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return info != null;
}
/**
* 检查手机上是否安装了指定的软件
*/
public static boolean isAvailable(Context context, File file) {
return isAvailable(context, getPackageName(context, file.getAbsolutePath()));
}
/**
* 根据文件路径获取包名
*/
public static String getPackageName(Context context, String filePath) {
PackageManager packageManager = context.getPackageManager();
PackageInfo info = packageManager.getPackageArchiveInfo(filePath, PackageManager.GET_ACTIVITIES);
if (info != null) {
ApplicationInfo appInfo = info.applicationInfo;
return appInfo.packageName; //得到安装包名称
} else {
return "";
}
}
/**
* 通过路径安装APK兼容Android 9以上
*
* @param context 上下文
* @param filePath apk文件路径
*/
public static void installApp(Context context, String filePath) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
installAppatPie(context, filePath);
} else {
installApps(filePath);
}
}
public static boolean installApps(String apkPath) {
Toaster.show("正在安装应用");
Process process = null;
BufferedReader successResult = null;
BufferedReader errorResult = null;
StringBuilder successMsg = new StringBuilder();
StringBuilder errorMsg = new StringBuilder();
try {
process = new ProcessBuilder("pm", "install", "-i", BuildConfig.APPLICATION_ID, "--user", "0", apkPath).start();
successResult = new BufferedReader(new InputStreamReader(process.getInputStream()));
errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String s;
while ((s = successResult.readLine()) != null) {
successMsg.append(s);
}
while ((s = errorResult.readLine()) != null) {
errorMsg.append(s);
}
} catch (Exception e) {
Log.e("installApps1", e.getMessage());
} finally {
try {
if (successResult != null) {
successResult.close();
}
if (errorResult != null) {
errorResult.close();
}
} catch (Exception e) {
Log.e("installApps2", e.getMessage());
}
if (process != null) {
process.destroy();
}
}
Log.e("result", "" + errorMsg.toString());
//如果含有“success”认为安装成功
Log.e("installApp", successMsg.toString());
// if (!successMsg.toString().equalsIgnoreCase("success")) {
// install(context, new File(apkPath));
// }
return successMsg.toString().equalsIgnoreCase("success");
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public static void installAppatPie(Context context, String apkFilePath) {
File file = new File(apkFilePath);
PackageInstaller packageInstaller = context.getPackageManager().getPackageInstaller();
PackageInstaller.SessionParams sessionParams = new PackageInstaller.SessionParams(PackageInstaller
.SessionParams.MODE_FULL_INSTALL);
sessionParams.setSize(file.length());
int sessionId = createSession(packageInstaller, sessionParams);
if (sessionId != -1) {
boolean copySuccess = copyApkFile(packageInstaller, sessionId, apkFilePath);
if (copySuccess) {
install(packageInstaller, sessionId, context);
}
}
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private static boolean copyApkFile(PackageInstaller pi, int sessionId, String apkFilePath) {
boolean success = false;
File apkFile = new File(apkFilePath);
PackageInstaller.Session session = null;
try {
session = pi.openSession(sessionId);
OutputStream out = session.openWrite("app.apk", 0, apkFile.length());
FileInputStream input = new FileInputStream(apkFile);
int read = 0;
byte[] buffer = new byte[65536];
// while (read != -1) {
// read = input.read(buffer);
// out.write(buffer, 0, read);
// }
while (true) {
read = input.read(buffer);
if (read == -1) {
session.fsync(out);
success = true;
out.close();
input.close();
break;
}
out.write(buffer, 0, read);
}
} catch (IOException e) {
e.printStackTrace();
Log.e("fht", "copyApkFile" + e.getMessage());
}
return success;
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private static void install(PackageInstaller packageInstaller, int sessionId, Context context) {
try {
PackageInstaller.Session session = packageInstaller.openSession(sessionId);
Intent intent = new Intent(context, InstallResultReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
context,
1, intent,
PendingIntent.FLAG_UPDATE_CURRENT
);
session.commit(pendingIntent.getIntentSender());
} catch (IOException e) {
e.printStackTrace();
}
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private static int createSession(PackageInstaller packageInstaller, PackageInstaller.SessionParams sessionParams) {
int sessionId = -1;
try {
sessionId = packageInstaller.createSession(sessionParams);
} catch (IOException e) {
e.printStackTrace();
}
return sessionId;
}
/**
* 静默卸载应用
*
* @param context
* @param pkg
*/
public static void UninstallAPP(Context context, String pkg) {
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
Log.e("UninstallAPP", "call " + Thread.currentThread().getName());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
ApkUtils.uninstall(context, pkg);
} else {
ApkUtils.deleteApkInSilence(pkg);
}
emitter.onNext(pkg);
}
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
Log.e("UninstallAPP", "onSubscribe: ");
}
@Override
public void onNext(String s) {
Log.e("UninstallAPP", "onNext " + Thread.currentThread().getName());
Log.e("UninstallAPP", "onNext: " + s);
}
@Override
public void onError(Throwable e) {
Log.e("UninstallAPP", "onError: " + e.getMessage());
}
@Override
public void onComplete() {
Log.e("UninstallAPP", "onComplete: ");
}
});
}
/**
* 根据包名卸载应用
*
* @param packageName 包名
*/
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public static void uninstall(Context context, String packageName) {
Intent broadcastIntent = new Intent(context, InstallResultReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 1,
broadcastIntent, PendingIntent.FLAG_UPDATE_CURRENT);
PackageInstaller packageInstaller = context.getPackageManager().getPackageInstaller();
packageInstaller.uninstall(packageName, pendingIntent.getIntentSender());
}
public static void deleteApkInSilence(String packageName) {
Class<?> pmService;
Class<?> activityTherad;
Method method;
try {
activityTherad = Class.forName("android.app.ActivityThread");
Class<?> paramTypes[] = getParamTypes(activityTherad, "getPackageManager");
method = activityTherad.getMethod("getPackageManager", paramTypes);
Object PackageManagerService = method.invoke(activityTherad);
pmService = PackageManagerService.getClass();
Class<?> paramTypes1[] = getParamTypes(pmService, "deletePackageAsUser");
method = pmService.getMethod("deletePackageAsUser", paramTypes1);
//getUserId
method.invoke(PackageManagerService, packageName, null, getUserId(Binder.getCallingUid()), 0x00000040);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
private static Class<?>[] getParamTypes(Class<?> cls, String mName) {
Class<?> cs[] = null;
Method[] mtd = cls.getMethods();
for (int i = 0; i < mtd.length; i++) {
if (!mtd[i].getName().equals(mName)) {
continue;
}
cs = mtd[i].getParameterTypes();
}
return cs;
}
public static final int PER_USER_RANGE = 100000;
public static int getUserId(int uid) {
return uid / PER_USER_RANGE;
}
public static boolean checkAppUpdate(Context context, AppInfo appUpdateInfo) {
String packageName = appUpdateInfo.getApp_package();
long versionCode = appUpdateInfo.getApp_version_code();
return checkAppUpdate(context, packageName, versionCode);
}
public static boolean checkAppUpdate(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 ariaDownload(Context context, String url, AppInfo ariaDownloadInfo) {
Log.e(TAG, "ariaDownload: " + ariaDownloadInfo);
String fileName = Utils.getFileNamefromURL(url);
String app_md5 = ariaDownloadInfo.getApp_md5();
Log.e("ariaDownload", "app_md5 = " + app_md5);
File file = new File(Utils.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)) {
installApp(context, file.getAbsolutePath());
} else {
file.delete();
Aria.download(context)
.load(url) //读取下载地址
.setFilePath(Utils.getDownLoadPath(context) + fileName)
.ignoreFilePathOccupy()
.setExtendField(GsonUtils.toJSONString(ariaDownloadInfo))
.create(); //启动下载}
}
} else {
Aria.download(context)
.load(url) //读取下载地址
.setFilePath(Utils.getDownLoadPath(context) + fileName)
.ignoreFilePathOccupy()
.setExtendField(GsonUtils.toJSONString(ariaDownloadInfo))
.create(); //启动下载}
}
}
}