禁默安装 App 内升级调用 PackageInstaller 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 public static void installApk1( final @NonNull File apkFile, final @NonNull PermissionsActivity permissionsActivity) { String apkName = "appInstall.apk"; long apkFileLength = apkFile.length(); PackageManager pm = permissionsActivity.getPackageManager(); PackageInstaller packageInstaller = pm.getPackageInstaller(); packageInstaller.registerSessionCallback(new PackageInstaller.SessionCallback() { @Override public void onCreated(int sessionId) { Log.e(TAG, "Install Start sessionId-> " + sessionId); } @Override public void onBadgingChanged(int sessionId) {} @Override public void onActiveChanged(int sessionId, boolean active) {} @Override public void onProgressChanged(int sessionId, float progress) {} @Override public void onFinished(int sessionId, boolean success) { if (success) { Log.e(TAG, "Silent Install Success"); } else { Log.e(TAG, "Silent Install Fail"); } } }); int count; int sessionId; byte[] buffer = new byte[65536]; InputStream inputStream; OutputStream outputStream; PackageInstaller.Session session = null; PackageInstaller.SessionParams sessionParams; try { sessionParams = new PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL); sessionId = packageInstaller.createSession(sessionParams); session = packageInstaller.openSession(sessionId); inputStream = new FileInputStream(apkFile); outputStream = session.openWrite(apkName, 0, apkFileLength); while((count = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, count); float progress = ((float)count / (float)apkFileLength); session.setStagingProgress(progress); } session.fsync(outputStream); inputStream.close(); outputStream.flush(); outputStream.close(); Intent intent = new Intent(); intent.setAction("xinan.intent.action.APP_INSTALL"); PendingIntent pendingIntent = PendingIntent.getBroadcast(permissionsActivity.getBaseContext(), 0, intent, 0); session.commit(pendingIntent.getIntentSender()); } catch (Exception e) { e.printStackTrace(); if (session != null) { session.abandon(); } } finally { } }
注册系统服务 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 public class AutoStartAppReceiver extends BroadcastReceiver { private final String TAG = "AutoStartReceiver"; private final String ACTION_BOOT = "android.intent.action.BOOT_COMPLETED"; private final String ACTION_CUSTOM_BOOT = "xinan.intent.action.BOOT_COMPLETED"; private final String ACTION_CUSTOM_AFTER_SYSTEM_UI = "xinan.intent.action.AfterStartSystemUI"; private final String ACTION_APP_INSTALL = "xinan.intent.action.APP_INSTALL"; /** * 接收广播消息后都会进入 onReceive 方法,然后要做的就是对相应的消息做出相应的处理 * * @param context 表示广播接收器所运行的上下文 * @param intent 表示广播接收器收到的Intent */ @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); Log.i(TAG, "onReceive:" + action); if (ACTION_BOOT.equals(action) || ACTION_CUSTOM_AFTER_SYSTEM_UI.equals(action) || ACTION_CUSTOM_BOOT.equals(action)) { launchApp(context); } else if (ACTION_APP_INSTALL.equals(action)) { Bundle extras = intent.getExtras(); int status = extras.getInt(PackageInstaller.EXTRA_STATUS); String message = extras.getString(PackageInstaller.EXTRA_STATUS_MESSAGE); Log.i(TAG, "onReceive status:" + status + " message:" + message); switch (status) { case PackageInstaller.STATUS_PENDING_USER_ACTION: break; case PackageInstaller.STATUS_SUCCESS: Log.d(TAG, "Install succeeded!"); launchApp(context); break; case PackageInstaller.STATUS_FAILURE: case PackageInstaller.STATUS_FAILURE_ABORTED: case PackageInstaller.STATUS_FAILURE_BLOCKED: case PackageInstaller.STATUS_FAILURE_CONFLICT: case PackageInstaller.STATUS_FAILURE_INCOMPATIBLE: case PackageInstaller.STATUS_FAILURE_INVALID: case PackageInstaller.STATUS_FAILURE_STORAGE: Log.e(TAG, "Install failed!" + status + ", " + message); break; default: Log.e(TAG, "Unrecognized status received from installer: " + status); } } } private void launchApp(Context context) { try { String packageName = "com.xinan.ubox"; PackageManager pm = context.getPackageManager(); if (checkApp(pm, packageName)) { if (!isRunning(context, packageName)) { Log.i(TAG, "app start:" + packageName); Intent intentMainActivity = pm.getLaunchIntentForPackage(packageName); intentMainActivity.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(intentMainActivity); } else { Log.i(TAG, "app is running:" + packageName); } } else { Log.i(TAG, "app not exist:" + packageName); } } catch (Exception e) { Log.i(TAG, "onReceive error:" + e.getLocalizedMessage()); } } private boolean checkApp(PackageManager pm, String packageName) { try { PackageInfo packageInfo = pm.getPackageInfo(packageName, 0); return packageInfo != null; } catch (Exception e) { return false; } } public boolean isRunning(Context context, String packageName) { try { ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); //获取当前所有存活task的信息 List<ActivityManager.RunningTaskInfo> processInfos = activityManager.getRunningTasks(Integer.MAX_VALUE); //遍历,若task的name与当前task的name相同,则返回true,否则,返回false for (ActivityManager.RunningTaskInfo process : processInfos) { if (process.baseActivity.getPackageName().equals(packageName) || process.topActivity.getPackageName().equals(packageName)) { return true; } } return false; } catch (Exception e) { Log.i(TAG, "isRunning error:" + e.getLocalizedMessage()); return false; } } }
manifest 注册接收器 1 2 3 4 5 6 7 8 9 10 11 12 13 <!--注册接收系统开机广播消息的广播接收者--> <receiver android:name=".AutoStartAppReceiver" android:enabled="true" android:exported="true"> <intent-filter android:priority="1000"> <action android:name="android.intent.action.BOOT_COMPLETED" /> <action android:name="xinan.intent.action.AfterStartSystemUI" /> <action android:name="xinan.intent.action.APP_INSTALL" /> <action android:name="xinan.intent.action.BOOT_COMPLETED" /> <category android:name="android.intent.category.HOME" /> </intent-filter> </receiver>
参考资料 https://blog.csdn.net/sinat_35622297/article/details/83995957?spm=1001.2101.3001.6650.11&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-11-83995957-blog-128485823.235%5Ev27%5Epc_relevant_multi_platform_whitelistv3&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-11-83995957-blog-128485823.235%5Ev27%5Epc_relevant_multi_platform_whitelistv3&utm_relevant_index=17
https://stackoverflow.com/questions/58085899/android-10-no-activity-found-to-handle-intent
https://zhuanlan.zhihu.com/p/183960413
https://android.googlesource.com/platform/development/+/master/samples/ApiDemos/src/com/example/android/apis/content/InstallApkSessionApi.java