调用原生Android安装apk

1. Android

1.1 安装Android Studio

过程略。

1.2 新建安卓工程

记住自己的Package name。

然后在编辑器左上角,切换模式为Project,如下图:

1.3 新建Module

在工程中新建一个Module,取名为如下图:

1.4 功能代码

接着找到新建的Module,然后在Src—>Main—>java—>com.nofun.install文件夹下新建两个Class,见下图:

脚本代码如下:

package com.nofun.install;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class InitializeApkBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if(Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())){
            InstallApkUtils.removeApkFile(InstallApkUtils.apkFilePath);
        }
        if(Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())){

        }
        if(Intent.ACTION_PACKAGE_REPLACED.equals(intent.getAction())){

        }
    }
}
package com.nofun.install;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.os.Build;

import androidx.core.content.FileProvider;

import java.io.File;

public class InstallApkUtils {
    private Context mContext;
    private static InstallApkUtils mInstallApkUtils = null;
    private InitializeApkBroadcastReceiver apkBroadcastReceiver;
    public static String apkFilePath;

    public InstallApkUtils(Context context) {
        this.mContext = context;
    }

    public static InstallApkUtils getInstance(Context context){
        if (mInstallApkUtils == null) {
            mInstallApkUtils = new InstallApkUtils(context);
        }
        return mInstallApkUtils;
    }

    //安装Apk
    public void installApk(String filePath){
        apkFilePath = filePath;
        File apkFile = new File(filePath);
        if(!apkFile.exists()){
            return;
        }

        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);


        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){//安卓7.0以上
            Uri apkUri = FileProvider.getUriForFile(mContext,mContext.getPackageName() + ".fileProvider",apkFile);
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            intent.setDataAndType(apkUri,"application/vnd.android.package-archive");
        }
        else {//安卓7.0以下
            intent.setDataAndType(Uri.parse("file://" + apkFile.toString()),"application/vnd.android.package-archive");
        }
        if(mContext.getPackageManager().queryIntentActivities(intent,0).size() > 0){
            mContext.startActivity(intent);
        }
    }

    //注册广播
    public void registerBroadcast(){
        if(apkBroadcastReceiver == null){
            apkBroadcastReceiver = new InitializeApkBroadcastReceiver();
        }
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
        intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
        intentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED);
        intentFilter.addDataScheme("package");
        mContext.registerReceiver(apkBroadcastReceiver,intentFilter);
    }

    //取消注册广播
    public void unregisterBroadcast(){
        if(apkBroadcastReceiver != null){
            mContext.unregisterReceiver(apkBroadcastReceiver);
            apkBroadcastReceiver = null;
        }
    }

    //删除apk文件
    public static void removeApkFile(String path){
        File apkFile = new File(path);
        if(apkFile.isFile() && apkFile.exists()){
            apkFile.delete();
        }
    }
}

1.5 修改AndroidManifest.xml

注意,是Module下面的AndroidManifest,不是工程中的:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.nofun.install">
    <uses-permission android:name="android.permission.REPLACE_EXISTING_PACKAGE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission
    android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
    <application>
        <meta-data
            android:name="com.google.android.actions"
            android:resource="@xml/provider_paths" />
        <provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="${applicationId}.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/provider_paths" />
        </provider>
    </application>
</manifest>

1.6 新建provider_paths.xml

也是在Module下面新建,目录结果如上,如果没有xml文件夹,就新建这个文件夹。

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-path name="publicDir" path="." />
</paths>

1.7 Build

点击"Make Project"进行构建,完成后在Module的build—>outputs—>aar文件夹下就能看到生成的aar文件了。

2.Unity 

2.1 添加aar

将上面生成的aar文件放到Unity的Plugins/Android文件夹中。

2.2 调用脚本

using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
 
public class ApplicationStoreManager : MonoBehaviour
{
    private AndroidJavaObject installApkUtils;
 
    // Start is called before the first frame update
    void Start()
    {
    	AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
        AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
        AndroidJavaClass installApkUtilsClass = new AndroidJavaClass("com.nofun.install.InstallApkUtils");
        installApkUtils = installApkUtilsClass.CallStatic<AndroidJavaObject>("getInstance", currentActivity);
        installApkUtils.Call("registerBroadcast");
    }
 
    private void OnDestroy()
    {
        installApkUtils.Call("unregisterBroadcast");
    }
 
    /// <summary>
    /// 安装Apk
    /// </summary>
    /// <param name="filePath"> Apk文件路径 </param>
    public void InstallApk(string filePath)
    {
        installApkUtils.Call("installApk", filePath);
    }
}

2.3 工程设置

2.3.1 Publishing Settings

在Publishing Settings勾选下图的选项:

2.3.2 修改配置文件

上面两个选项勾选后,会在Asset—>Plugins—>Android文件夹中生成gradleTemplate.propertiesmainTemplate.gradle两个文件,需要分别修改这两个文件。

mainTemplate.gradle,在dependencies 块中添加一行代码:

 implementation 'androidx.appcompat:appcompat:1.2.0'

 

gradleTemplate.properties,在文件最后面添加以下内容:

android.overridePathCheck=true
android.useAndroidX=true
android.enableJetifier=true

2.4 打包

接着在Unity中打包即可,亲测2021版本有效。