There are many schemes for Android silent installation, such as using ProcessBuilder or Runtime.getRuntime().exec() to run the PM istall command, but this method needs su first, root permission, or reflection to get PackageManager.installPackage(), which is also cumbersome to use. At the same time, system permission needs to be obtained. Above API21, packageinstaller.section can be used to achieve silent installation For installation, the interface also needs to obtain the system permission android.permission.INSTALL_PACKAGES, not to mention, directly code.
public void install(@NonNull Context context,@NonNull String path) throws Exception { File file=new File(path); String apkName=path.substring(path.lastIndexOf(File.separator)+1,path.lastIndexOf(".apk")); //Get PackageInstaller PackageInstaller packageInstaller = context.getPackageManager() .getPackageInstaller(); PackageInstaller.SessionParams params=new PackageInstaller .SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL); PackageInstaller.Session session=null; OutputStream outputStream=null; FileInputStream inputStream=null; try { //Create Session int sessionId = packageInstaller.createSession(params); //Open Session session=packageInstaller.openSession(sessionId); //Get the output stream to write apk to session outputStream = session.openWrite(apkName, 0, -1); inputStream=new FileInputStream(file); byte[] buffer=new byte[4096]; int n; //Read apk file and write session while ((n=inputStream.read(buffer))>0){ outputStream.write(buffer,0,n); } //You need to close the flow after writing, otherwise the exception "files still open" will be thrown inputStream.close(); inputStream=null; outputStream.flush(); outputStream.close(); outputStream=null; //Configure the intent initiated after the installation is completed, usually to open the activity Intent intent=new Intent(); PendingIntent pendingIntent=PendingIntent.getActivity(mContext,0,intent,0); IntentSender intentSender = pendingIntent.getIntentSender(); //Submit to start installation session.commit(intentSender); } catch (IOException e) { throw new RuntimeException("Couldn't install package", e); } catch (RuntimeException e) { if (session != null) { session.abandon(); } throw e; }finally { closeStream(inputStream); closeStream(outputStream); } }
The comments have been explained clearly, so we won't explain them much. To get the status of the installation process, you can register the SessionCallback for PackageInataller before creating session
packageInstaller.registerSessionCallback(new PackageInstaller.SessionCallback() { @Override public void onCreated(int 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) { } });