Unity獲取手機(jī)本地應(yīng)用以及調(diào)起apk安裝、啟動app、安裝完成回調(diào)
1、獲取手機(jī)本地應(yīng)用。
創(chuàng)建AppInfo類和AppUtils類,用于接收獲取到的應(yīng)用列表。
Android層代碼AppInfo:
public class AppInfo {
private Drawable image;
private String appName;
private String packageName;
public AppInfo() {
}
public Drawable getImage() {
return image;
}
public void setImage(Drawable image) {
this.image = image;
}
public String getAppName() {
return appName;
}
public void setAppName(String appName) {
this.appName = appName;
}
public String getPackageName() {
return packageName;
}
public void setPackageName(String packageName) {
this.packageName = packageName;
}
}
Android層代碼AppUtils:
public class AppUtils {
private static final String TAG = "AppUtils";
public static List<AppInfo> scanLocalInstallAppList(PackageManager packageManager) {
List myAppInfos = new ArrayList();
try {
List packageInfos = packageManager.getInstalledPackages(0);
for (int i = 0; i < packageInfos.size(); i++) {
PackageInfo packageInfo = (PackageInfo) packageInfos.get(i);
//過濾掉系統(tǒng)app
if ((ApplicationInfo.FLAG_SYSTEM & packageInfo.applicationInfo.flags) != 0) {
continue;
}
AppInfo myAppInfo = new AppInfo();
String appName = packageInfo.applicationInfo.loadLabel(packageManager).toString();
myAppInfo.setAppName(appName);
myAppInfo.setPackageName(packageInfo.packageName);
if (packageInfo.applicationInfo.loadIcon(packageManager) == null) {
continue;
}
myAppInfo.setImage(packageInfo.applicationInfo.loadIcon(packageManager));
myAppInfos.add(myAppInfo);
}
} catch (Exception e) {
Log.e(TAG, "獲取應(yīng)用包信息失敗");
}
return myAppInfos;
}
}
Android層代碼獲取代碼:
List<AppInfo> appInfos = AppUtils.scanLocalInstallAppList(app.getPackageManager()); //app為主activity的單例,也就是onCreate里設(shè)置app=this。
for(int k=0;k<appInfos.size();k++)
{
String s1 = appInfos.get(k).getAppName();//應(yīng)用名
String s2 = appInfos.get(k).getPackageName();//應(yīng)用包名com.xxx.xx.xx
Drawable dw = appInfos.get(k).getImage();//應(yīng)用的icon
}
//安卓層獲取這些信息后,再傳遞給Unity。
2、Unity調(diào)起APK的安裝。
Unity代碼:
設(shè)置apk的路徑,假如在應(yīng)用的虛擬目錄下:
string apkPath = Application.persistentDataPath + "/" + apkName;
Android代碼:
public static void InstallAPK(String filePath) {
try {
File apkFile = new File(filePath);
if (apkFile.exists()) {
Intent intent = new Intent(Intent.ACTION_VIEW);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
Uri contentUri = FileProvider.getUriForFile(app, app.getPackageName()+".fileprovider", apkFile);
intent.setDataAndType(contentUri, "application/vnd.android.package-archive");
} else {
intent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
app.startActivity(intent);
} else {
}
}
catch (Exception ex)
{
}
}
Android需增加配置項(xiàng),寫在AndroidManifest.xml里。
權(quán)限:
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
設(shè)置Provider:
${applicationId}為包名的變量,可以改寫為com.xx.xx.xxx。
后面的.fileprovider需要與Android代碼中的.fileprovider的名字保持一致。
provider_paths要與xml的名字保持一致。
<provider
android:name="android.support.v4.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>
res目錄下的xml文件夾下增加provider_paths.xml,內(nèi)容為:
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path
name="external_storage_root"
path="." />
<files-path
name="files-path"
path="." />
<cache-path
name="cache-path"
path="." />
<!--/storage/emulated/0/Android/data/...-->
<external-files-path
name="external_file_path"
path="." />
<!--代表app 外部存儲區(qū)域根目錄下的文件 Context.getExternalCacheDir目錄下的目錄-->
<external-cache-path
name="external_cache_path"
path="." />
<!--配置root-path。這樣子可以讀取到sd卡和一些應(yīng)用分身的目錄,否則微信分身保存的圖片,就會導(dǎo)致 java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/999/tencent/MicroMsg/WeiXin/export1544062754693.jpg,在小米6的手機(jī)上微信分身有這個(gè)crash,華為沒有
-->
<root-path
name="root-path"
path="" />
</paths>
3、啟動App
//參數(shù)為app的包名,com.xx.xx.xx,如果app設(shè)置了禁止外部啟動,那就無法調(diào)起。如果沒有禁止外部調(diào)起,則能正常調(diào)起。
//app為主activity的單例,也就是onCreate里設(shè)置app=this。
public static void StartIntent(String pkgName) { try { Log.d("啟動的包名:",pkgName); Intent intent = app.getPackageManager().getLaunchIntentForPackage(pkgName); app.startActivity(intent); } catch (Exception ex) { Log.d("啟動的包名1:",ex.getMessage()); } }
4、安裝APP回調(diào)。
不止是安裝有回調(diào)、替換、卸載都有回調(diào)。
Android開啟監(jiān)聽:
public static void ReceiverApk(){
try{
installPkg = "";
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
intentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED);
intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
intentFilter.addDataScheme("package");
WXEntryActivity.app.registerReceiver(receiver, intentFilter);}
catch (Exception ex)
{}
}
Android卸載監(jiān)聽:
public static void unReceiverApk(){
isReceiverApk=false;
WXEntryActivity.app.unregisterReceiver(receiver);
}
WXEntryActivity為主activity的名稱。
app為主activity的單例,app=this.
Android回調(diào):
private static BroadcastReceiver receiver=new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.d("監(jiān)聽安裝",intent.getAction().toString());
if (intent.getAction().equals(Intent.ACTION_PACKAGE_ADDED)) {
String packageName = intent.getData().getSchemeSpecificPart();
//安裝
WXEntryActivity.mUnityPlayer.UnitySendMessage("Global","UnityReceiveAndroid","apkOperation|appInstall|" + packageName);
} else if (intent.getAction().equals(Intent.ACTION_PACKAGE_REPLACED)) {
String packageName = intent.getData().getSchemeSpecificPart();
// Log.e("~~~apk", packageName + "替換成功");
WXEntryActivity.mUnityPlayer.UnitySendMessage("Global","UnityReceiveAndroid","apkOperation|appReplace|" + packageName);
//jsbCallBack("appReplace",packageName);
} else if (intent.getAction().equals(Intent.ACTION_PACKAGE_REMOVED)) {
String packageName = intent.getData().getSchemeSpecificPart();
// Log.e("~~~apk", packageName + "卸載成功");
WXEntryActivity.mUnityPlayer.UnitySendMessage("Global","UnityReceiveAndroid","apkOperation|appRemove|" + packageName);
//jsbCallBack("appRemove",packageName);
}
}
};
WXEntryActivity.mUnityPlayer.UnitySendMessage為向Unity發(fā)送消息,通知Unity。
小時(shí)候我把老婆種到地下,長大了我能收獲一大堆老婆!
我是威少,我是一名Unity游戲的主程,我為自己帶鹽,希望此文能給您一點(diǎn)點(diǎn)微不足道的幫助,祝你成功!

浙公網(wǎng)安備 33010602011771號