Android 9.0静默安装与卸载app

最近在开发中有个需求就是要实现静默安装与卸载app的功能,而在PackageManager的api中安装与卸载的接口被隐藏,所以在另辟蹊径,下面把实现的代码分享下

import android.app.PendingIntent;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class InstallApkActivity extends AppCompatActivity implements View.OnClickListener{
    private String TAG ="MainActivity";
    private Button install_btn,uninstall_btn;
    private int mSessionId = -1;
    private PackageInstaller.SessionCallback mSessionCallback;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_install);
        init();
    }
    private void init() {
        install_btn = (Button) findViewById(R.id.btn_install);
        install_btn.setOnClickListener(this);
        uninstall_btn = (Button) findViewById(R.id.btn_uninstall);
        uninstall_btn.setOnClickListener(this);
        mSessionCallback = new InstallSessionCallback();
        getPackageManager().getPackageInstaller().registerSessionCallback(mSessionCallback);
    }
    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn_install:
                installApp("mnt/usb/26A8-0362/MyApp.apk");
                break;
            case R.id.btn_uninstall:
                uninstall("com.xinrui.myapplication");
                break;
        }
    }

    /**
     * 根据包名卸载应用
     *
     * @param packageName
     */
    public void uninstall(String packageName) {
        Intent broadcastIntent = new Intent(this, UnInstallResultReceiver.class);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 1,
                broadcastIntent, PendingIntent.FLAG_UPDATE_CURRENT);
        PackageInstaller packageInstaller = getPackageManager().getPackageInstaller();
        packageInstaller.uninstall(packageName, pendingIntent.getIntentSender());
    }

   /**
     * 适配android9的安装方法。
     * 全部替换安装
     */
    public void installApp(String apkFilePath) {
        File apkFile = new File(apkFilePath);
        if (!apkFile.exists()) {
            Log.d("MainActivity", "文件不存在");
            return;
        }

        PackageInfo packageInfo = mContext.getPackageManager().getPackageArchiveInfo(apkFilePath, PackageManager.GET_ACTIVITIES | PackageManager.GET_SERVICES);
        if (packageInfo != null) {
            String packageName = packageInfo.packageName;
            int versionCode = packageInfo.versionCode;
            String versionName = packageInfo.versionName;
            //Log.d("ApkActivity", "packageName=" + packageName + ", versionCode=" + versionCode + ", versionName=" + versionName);
        }

        PackageInstaller packageInstaller = mContext.getPackageManager().getPackageInstaller();
        PackageInstaller.SessionParams sessionParams
                = new PackageInstaller.SessionParams(PackageInstaller
                .SessionParams.MODE_FULL_INSTALL);
        sessionParams.setSize(apkFile.length());

        try {
            mSessionId = packageInstaller.createSession(sessionParams);
        } catch (IOException e) {
            e.printStackTrace();
        }

        //Log.d(TAG, "sessionId---->" + mSessionId);
        if (mSessionId != -1) {
            boolean copySuccess = onTransfesApkFile(apkFilePath);
            //Log.d(TAG, "copySuccess---->" + copySuccess);
            if (copySuccess) {
                execInstallAPP();
            }
        }
    }

    /**
     * 通过文件流传输apk
     *
     * @param apkFilePath
     * @return
     */
    private boolean onTransfesApkFile(String apkFilePath) {
        InputStream in = null;
        OutputStream out = null;
        PackageInstaller.Session session = null;
        boolean success = false;
        try {
            File apkFile = new File(apkFilePath);
            session = mContext.getPackageManager().getPackageInstaller().openSession(mSessionId);
            out = session.openWrite("base.apk", 0, apkFile.length());
            in = new FileInputStream(apkFile);
            int total = 0, c;
            byte[] buffer = new byte[1024 * 1024];
            while ((c = in.read(buffer)) != -1) {
                total += c;
                out.write(buffer, 0, c);
            }
            session.fsync(out);
            //Log.d(TAG, "streamed " + total + " bytes");
            success = true;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null != session) {
                session.close();
            }
            try {
                if (null != out) {
                    out.close();
                }
                if (null != in) {
                    in.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return success;
    }
    /**
     * 执行安装并通知安装结果
     *
     */
    private void execInstallAPP() {
        PackageInstaller.Session session = null;
        try {
            session = mContext.getPackageManager().getPackageInstaller().openSession(mSessionId);
            Intent intent = new Intent(mContext, InstallResultReceiver.class);
            PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext,
                    1, intent,
                    PendingIntent.FLAG_UPDATE_CURRENT);
            session.commit(pendingIntent.getIntentSender());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null != session) {
                session.close();
            }
        }
    }

    private class InstallSessionCallback extends PackageInstaller.SessionCallback {
        @Override
        public void onCreated(int sessionId) {
            // empty
        }

        @Override
        public void onBadgingChanged(int sessionId) {
            // empty
        }

        @Override
        public void onActiveChanged(int sessionId, boolean active) {
            // empty
        }

        @Override
        public void onProgressChanged(int sessionId, float progress) {
            if (sessionId == mSessionId) {
                int progres = (int) (Integer.MAX_VALUE * progress);
            }
        }

        @Override
        public void onFinished(int sessionId, boolean success) {
            // empty, finish is handled by InstallResultReceiver
            if (mSessionId == sessionId) {
                if (success) {
                    Log.d("MainActivity", "onFinished() 安装成功");
                } else {
                    Log.d("MainActivity", "onFinished() 安装失败");
                }

            }
        }
    }
}
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInstaller;
import android.util.Log;

public class InstallResultReceiver extends BroadcastReceiver {
    private static final String TAG = "MainActivity";

    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        Log.d(TAG, "收到安装反馈广播了 action:" + action);
        if (intent != null) { //安装的广播
            final int status = intent.getIntExtra(PackageInstaller.EXTRA_STATUS,
                    PackageInstaller.STATUS_FAILURE);
            if (status == PackageInstaller.STATUS_SUCCESS) {
                // success
                Log.d(TAG, "APP Install Success!");
                // InstallAPP.getInstance().sendInstallSucces();
            } else {
                String msg = intent.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE);
                Log.e(TAG, "Install FAILURE status_massage" + msg);
                //InstallAPP.getInstance().sendFailure(msg);
            }
        }
    }
}
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInstaller;
import android.util.Log;

public class UnInstallResultReceiver extends BroadcastReceiver {
    private static final String TAG = "MainActivity";

    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        Log.d(TAG, "收到卸载反馈广播了");
        if (intent != null) { //安装的广播
            final int status = intent.getIntExtra(PackageInstaller.EXTRA_STATUS,
                    PackageInstaller.STATUS_FAILURE);
            if (status == PackageInstaller.STATUS_SUCCESS) {
                // success
                Log.d(TAG, "APP UnInstall Success!");
                // InstallAPP.getInstance().sendInstallSucces();
            } else {
                String msg = intent.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE);
                Log.e(TAG, "UnInstall FAILURE status_massage" + msg);
                //InstallAPP.getInstance().sendFailure(msg);
            }
        }
    }
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.xinrui.headsettest">
    <!--静默安装权限-->
    <uses-permission
        android:name="android.permission.INSTALL_PACKAGES"
        tools:ignore="ProtectedPermissions" />
    <!--应用卸载权限-->
    <uses-permission android:name="permission.REQUEST_INSTALL_PACKAGES" />
    <uses-permission android:name="permission.REQUEST_DELETE_PACKAGES" />
    <uses-permission
        android:name="android.permission.DELETE_PACKAGES"
        tools:ignore="ProtectedPermissions" />

    <!--读写外部存储权限-->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <!--允许装载和卸载文件系统权限-->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <activity android:name=".MainActivity">
            <!--<intent-filter>-->
                <!--<action android:name="android.intent.action.MAIN" />-->

                <!--<category android:name="android.intent.category.LAUNCHER" />-->
            <!--</intent-filter>-->
        </activity>
        <activity android:name=".AlamActivity">

            <!-- <intent-filter> -->
            <!-- <action android:name="android.intent.action.MAIN" /> -->


            <!-- <category android:name="android.intent.category.LAUNCHER" /> -->
            <!-- </intent-filter> -->
        </activity>
        <activity android:name=".InstallApkActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <receiver android:name=".AlarmBroadCast" />
        <receiver android:name=".AlarmBroadcastReciver" />
        <receiver
            android:name=".InstallResultReceiver"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="android.content.pm.extra.STATUS"/>
            </intent-filter>
        </receiver>
        <receiver
            android:name=".UnInstallResultReceiver"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="android.content.pm.extra.STATUS"/>
            </intent-filter>
        </receiver>
    </application>

</manifest>

你可能感兴趣的:(android)