安卓静默安装方法

在Android 6.0到Android 9.0操作系统中,谷歌已经提供了原生API方法来进行应用的静默安装,称为“Package Installer Session”。但是需要注意的是,这方法需要设备在所有者的设备上儿且有系统权限,例如:系统应用。因此,除非你的App有这样的权限,否则不能被直接在用户的设备上用这种方法进行静默安装。


前提:不管是方案一和方案二

1,需要在清单文件添加  入权限


    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.EXPAND_STATUS_BAR" /> 
    <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" />


    <uses-permission android:name="androidpermissionBIND DEVICEADMIN" />

 2,在清单文件application标签下添加如下

 coreApp="true"
 android:sharedUserId="android.uid.system"
 android:supportsRtl="true"  
 android:usesCleartextTraffic="true"       


方案一

以下是一种典型的使用方法:

class InstallUtil {
    private Context mContext;
    private String mApkFilePath;
    private static String TAG = "InstallUtil";
    private static int UN_INSTALL_SUCCESS = 1;

    public InstallUtil(Context context, String apkFilePath) {
        this.mContext = context;
        this.mApkFilePath = apkFilePath;
    }

    @RequiresApi(api = 24)
    public void install24() {
        boolean isGranted = isGranted();
        if (isGranted) {
            install();
        } else {
            Toast.makeText(mContext,"请开启本应用的安装权限",Toast.LENGTH_SHORT).show();
        }
    }

    public boolean isGranted() {
        return !TextUtils.isEmpty(mApkFilePath);
    }

    @RequiresApi(api = 26)
    private void install() {
        File file = new File(mApkFilePath);
        try {
            PackageInstaller packageInstaller = mContext.getPackageManager().getPackageInstaller();
            PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL);
            params.setSize(file.length());
            int sessionId = packageInstaller.createSession(params);
            PackageInstaller.Session session = packageInstaller.openSession(sessionId);
            InputStream in = new FileInputStream(file);
            OutputStream out = session.openWrite("CocosDemo", 0, file.length());
            byte[] buffer = new byte[65536];
            int c;
            while ((c = in.read(buffer)) != -1) {
                out.write(buffer, 0, c);
            }
            session.fsync(out);
            in.close();
            out.close();
            session.commit(PendingIntent.getBroadcast(mContext, sessionId,
                    new Intent("android.intent.action.PACKAGE_ADDED"), 0).getIntentSender());
        } catch (Exception e) {
            Log.e(TAG,"安装失败:"+e.getMessage());
            e.printStackTrace();
        }
    }
}

在方法install24里检测了是否有安装权限,如果有就进行安装。在我们安装之前都是要检测一下你的App是否获得了安装权限,如果没有的话就需要用户手动去开启。

这是一个比较简单的实现,并没有兼容所有的Android设备和版本。实际上,Android设备的厂商和版本非常多,可能每个都有自己不同的实现方式和限制,因此这个静默安装的方法可能不是所有设备都能使用

方案二

下面是一个Android静默安装的示例方法,它在Android 6.0到9.0的版本下都可以运行,并可以返回一个标示安装状态的boolean值。注意,此方法需要应用具有系统级别的权限。

需要在 AndroidManifest.xml 文件中添加安装应用的权限:

Java方法部分:

import android.content.Context;
import android.content.pm.PackageInstaller;
import android.os.Build;

public class InstallerUtil {
    
    public static boolean installPackage(Context context, String apkPath) {
        if(context == null || apkPath == null){
            return false;
        }
        try {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                PackageInstaller packageInstaller = context.getPackageManager().getPackageInstaller();
                PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
                        PackageInstaller.SessionParams.MODE_FULL_INSTALL);
                params.setAppPackageName(packageName);
                int sessionId = packageInstaller.createSession(params);
                PackageInstaller.Session session = packageInstaller.openSession(sessionId);
                OutputStream outputStream = session.openWrite(apkPath, 0, -1);
                File file = new File(apkPath);
                InputStream inputStream = new FileInputStream(file);
                byte[] buffer = new byte[65536];
                int c;
                while ((c = inputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, c);
                }
                session.fsync(outputStream);
                inputStream.close();
                outputStream.close();
                session.commit(Intents.getPendingIntent(context, sessionId, createInstallIntent(), 0).getIntentSender());
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }
}
这段代码的核心思想是创建一个Package Installer的session来进行安装。代码依次执行的是:创建SessionParams,然后创建PackageInstaller.Session, 并将apk文件写入到Session。在写入完成后,这个Session会commit,然后Package Installer会处理这个Session来完成安装过程。
注意,android从8.0开始增加了未知安装的权限检查,所以,如果你的应用要在8.0及以后的版本运行,你需要在安装APK前检查并请求安装未知应用源的权限。
但是,这个方法需要你的应用拥有系统级别的权限,也就是说,你的应用必须被签名并安装到/system/priv-app目录下才能正常工作,不然会出现安全异常。
战线,对于6.0到9.0版本这个范围内的静默安装,是非常有挑战性的,因为涉及到系统级别的API调用与权限,一个完全免root,兼容性好,可以静默安装的方法是相当困难的。对于普通应用开发者来说,要实现真正的静默安装,基本上是无解的。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

来之梦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值