Android Apk Download and Silent Installation

Foreword:

Our App is a customized Pad, so it has been signed by the system, but I have been searching for a long time to find the right one for silent installation, and then it is the code

The first is the method of Apk download

    //  文件保存路径
    private String mSavePath;
    //  版本名称
    private String mVersion_name = "/名称.apk";

  	/*
     * 开启新线程下载apk文件
     */
    private void downloadAPK(String mUrl) {
    
    
        new Thread(new Runnable() {
    
    
            @Override
            public void run() {
    
    
                try {
    
    
                    if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
    
    
                        String sdPath = Environment.getExternalStorageDirectory() + "/";
//                      文件保存路径
//                        mSavePath = sdPath + "jikedownload";
                        mSavePath = "/data/user/0/包名/files";
//                        mSavePath = "/data/local/tmp/";
                        File dir = new File(mSavePath);
                        if (!dir.exists()) {
    
    
                            dir.mkdir();
                        }
                        // 下载文件
                        HttpURLConnection conn = (HttpURLConnection) new URL(mUrl).openConnection();
                        conn.connect();
                        InputStream is = conn.getInputStream();
                        int length = conn.getContentLength();
                        File apkFile = new File(mSavePath, mVersion_name);
                        FileOutputStream fos = new FileOutputStream(apkFile);

                        int count = 0;
                        byte[] buffer = new byte[1024];
                        while (!mIsCancel) {
    
    
                            int numread = is.read(buffer);
                            count += numread;
                            // 计算进度条的当前位置
                            mProgress = (int) (((float) count / length) * 100);
                            Log.e("Base", "下载进度" + mProgress);
                            // 下载完成
                            if (numread < 0) {
    
    
                                Log.e("Base", "下载完成");
//                                mUpdateProgressHandler.sendEmptyMessage(2);
                                //静默安装
                                StringBuilder append = new StringBuilder().append(mSavePath).append(mVersion_name);
                                boolean installResult = Install.silentInstallApk(mContext,append.toString());
                                Log.e("Base", "安装结果" + installResult);
//                                break;
                            }
                            fos.write(buffer, 0, numread);
                        }
                        fos.close();
                        is.close();
                    }
                } catch (Exception e) {
    
    
                    e.printStackTrace();
                }
            }
        }).start();
    }

Then there is the code for silent installation

/**
 * 静默安装
 */
public class Install {
    
    
    private final static SynchronousQueue<Intent> mInstallResults = new
            SynchronousQueue<>();

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public static synchronized boolean silentInstallApk(Context context,
                                                        final String apkFilePath) {
    
    
        boolean ret = false;
        File apkFile = new File(apkFilePath);
        PackageInstaller installer = context.getPackageManager().getPackageInstaller();
        PackageInstaller.SessionParams sessionParams = new
                PackageInstaller.SessionParams(
                PackageInstaller.SessionParams.MODE_FULL_INSTALL);
        sessionParams.setSize(apkFile.length());
        int sessionId = createSession(installer, sessionParams);
        if (sessionId != -1) {
    
    
            boolean isCopyOk = copyInstallApkFile(sessionId, installer, apkFilePath);
            if (isCopyOk) {
    
    
                boolean isInstalled = installPackage(context, sessionId,
                        installer, apkFilePath);
                if (isInstalled) {
    
    
                    ret = true;
                }
            }
        }
        return ret;
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private static int createSession(PackageInstaller installer,
                                     PackageInstaller.SessionParams sessionParams) {
    
    
        int sessionId = -1;
        try {
    
    
            sessionId = installer.createSession(sessionParams);
        } catch (IOException e) {
    
    
            e.printStackTrace();
        }
        return sessionId;
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private static boolean copyInstallApkFile(int sessionId, PackageInstaller installer,
                                              String apkFilePath) {
    
    
        InputStream in = null;
        OutputStream out = null;
        PackageInstaller.Session session = null;
        boolean ret = false;
        try {
    
    
            File apkFile = new File(apkFilePath);
            session = installer.openSession(sessionId);
            out = session.openWrite("base.apk", 0, apkFile.length());
            in = new FileInputStream(apkFile);
            File file = new File(String.valueOf(apkFile));
            if (file.exists()) {
    
    
                Log.i("Base", "存在");
            }
            int count;
            byte[] buffer = new byte[65536];
            while ((count = in.read(buffer)) != -1) {
    
    
                out.write(buffer, 0, count);
            }
            session.fsync(out);
            ret = true;
        } catch (IOException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            try {
    
    
                out.close();
            } catch (IOException e) {
    
    
                e.printStackTrace();
            }

            try {
    
    
                if (in != null) {
    
    
                    in.close();
                }
            } catch (IOException e) {
    
    
                e.printStackTrace();
            }
            session.close();
        }
        return ret;
    }
	
	    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private static boolean installPackage(Context context, int sessionId,
                                          PackageInstaller installer, String filePath) {
    
    
        PackageInstaller.Session session = null;
        boolean ret = false;
        try {
    
    
            session = installer.openSession(sessionId);
            Intent intent = new Intent();
            intent.setAction("com.example.install");
            PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 1, intent,
                    PendingIntent.FLAG_UPDATE_CURRENT);
            session.commit(pendingIntent.getIntentSender());
            final Intent intentResult = mInstallResults.poll(60, TimeUnit.SECONDS);
            //这个地方返回的*intentResult *为null,所以导致代用静默安装方法返回的值为**false**,但是app已经成功静默安装成功了,至于原因
            //笔者也暂时没有找到,如果有哪位看官懂,麻烦评论下,感谢
            if (intentResult != null) {
    
    
                final int status = intentResult.getIntExtra(PackageInstaller.EXTRA_STATUS,
                        PackageInstaller.STATUS_FAILURE);
                if (status == PackageInstaller.STATUS_SUCCESS) {
    
    
                    ret = true;
                }
            }
        } catch (Exception e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            session.close();
        }
        return ret;
    }

}

Finally, the permissions, must not forget

  <uses-permission android:name="android.permission.INSTALL_PACKAGES" />
  <uses-permission android:name="android.permission.BIND_DEVICE_ADMIN" />

This is all the code, there are a few points I want to declare, the first is to place the address of the Apk and the name of the Apk, you have to change it yourself; the second is the return value after calling the silent installation, in fact, it returns false , but The app was installed successfully silently. As for the reason, I didn’t find the specific reason for the interruption point. If anyone understands, please comment, thank you. Finally, the above is my conclusion based on my own experience and referring to some articles on the Internet, please refer to

Guess you like

Origin blog.csdn.net/m0_46366678/article/details/128042469