android apk巢狀 從一個apk啟動另外一個apk

yangxi_001發表於2016-07-26

a.apk-主應用  b.apk-被啟動應用

主要思想:把b.apk放到assets目錄下,由於有大小限制(1M),所以改名成b.mp3(因為mp3,jpg,png,mp4等不會檢查,不會限制大小),然後在用的時候再改回來

1.具體實現:

public void intallApp(Context context) {
try {
String path = context.getFilesDir().getAbsolutePath()+ "/b.apk";  //從assets中解壓到這個目錄

File f = new File(path);
if (!f.exists()) {
f.createNewFile();
}
InputStream is = context.getAssets().open("b.mp3");//assets裡的檔案在應用安裝後仍然存在於apk檔案中
inputStreamToFile(is, f);
String cmd = "chmod 777 " + f.getAbsolutePath();
Runtime.getRuntime().exec(cmd);
cmd = "chmod 777 " + f.getParent();
Runtime.getRuntime().exec(cmd);
// 嘗試提升上2級的父資料夾許可權,在閱讀外掛下載到手機儲存時,剛好用到了2級目錄
// /data/data/packagename/files/這個目錄下面所有的層級目錄都需要提升許可權,才可安裝apk,彈出安裝介面
cmd = "chmod 777 " + new File(f.getParent()).getParent();
Runtime.getRuntime().exec(cmd);
Intent intent = new Intent();
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setAction(android.content.Intent.ACTION_VIEW);

String type = "application/vnd.android.package-archive";
/* 設定intent的file與MimeType */
intent.setDataAndType(Uri.fromFile(f), type);
context.startActivity(intent);
} catch (ActivityNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}


public void inputStreamToFile(InputStream inputStream,File file){
///InputStream inputStream = null;
OutputStream outputStream = null;
try {
// read this file into InputStream
//inputStream = new FileInputStream("test.txt");
 
// write the inputStream to a FileOutputStream
outputStream = new FileOutputStream(file);
 
int read = 0;
byte[] bytes = new byte[1024];
 
while ((read = inputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, read);
}
 
System.out.println("Done!");
 
} catch (IOException e) {
e.printStackTrace();
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (outputStream != null) {
try {
// outputStream.flush();
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
 
}
}
}


2.如果是啟動已安裝的應用,實現如下:

public boolean startApp(Context context, String packageName) {
//String packageName = "XXX";
Intent intent = new Intent(Intent.ACTION_MAIN, null);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
PackageManager pm = context.getPackageManager();
List<ResolveInfo> listInfos = pm.queryIntentActivities(intent, 0);
String className = null;
for (ResolveInfo info : listInfos) {
if (packageName.equals(info.activityInfo.packageName)) {
className = info.activityInfo.name;
break;
}
}
if (className != null && className.length() > 0) {
intent.setComponent(new ComponentName(packageName, className));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
context.startActivity(intent);
return true;
}
return false;
}

如果你知道包名,還知道作為啟動的那activity的類名,就更簡單了,就可以省掉上面查詢的過程,直接啟動。

相關文章