Android APK のダウンロードとサイレント インストール

序文:

私たちのアプリはカスタマイズされたパッドなので、システムによって署名されていますが、サイレントインストールに適したものを見つけるために長い間探していました、そしてそれがコードです

まずはAPKのダウンロード方法です

    //  文件保存路径
    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();
    }

次に、サイレントインストール用のコードがあります

/**
 * 静默安装
 */
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;
    }

}

最後に忘れてはならないのが権限です。

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

これがすべてのコードです。宣言したい点がいくつかあります。1 つ目は、APK のアドレスと APK の名前を配置することです。これは自分で変更する必要があります。2 つ目は、サイレント メソッドを呼び出した後の戻り値です。実際にインストールすると false が返されますが、アプリはサイレントで正常にインストールされました。理由については、中断ポイントの具体的な理由が見つかりませんでした。理解できる方がいらっしゃいましたら、コメントしてください。ありがとうございます。最後に、上記は私自身の経験とインターネット上の記事を参考にした私の結論です。以下を参照してください。

おすすめ

転載: blog.csdn.net/m0_46366678/article/details/128042469