當初為了達到自動安裝APK,而不會跳出任何訊息,且又不能使用非法的API或Java Reflection。
研究超久,試了網路上好多人的做法,一直無法成功,直到以下的方法才有效達到我想要的效果。
由於是很久以前試出來的,我也忘記出處在哪了,為了預防哪天我寫的的測試程式不小心被我清掉。因此在這裡備份一下程式碼。
private void autoInstall(Context context) {
String apkfile = context.getFilesDir() + "/MyTest.apk";
String ACTION_INSTALL_COMPLETE = "cm.android.intent.action.INSTALL_COMPLETE";
try {
PackageInstaller pi = context.getPackageManager().getPackageInstaller();
//給定模式,創建新的參數,創建新安裝會話,返回唯一 Id
int sessionId= pi.createSession(new PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL));
//打開現有會話,主動執行工作
PackageInstaller.Session session = pi.openSession(sessionId);
long sizeBytes = 0;
final File file = new File(apkfile);
if (file.isFile()) {
sizeBytes = file.length();
}
InputStream in = null;
OutputStream out = null;
in = new FileInputStream(apkfile);
//打開一個流,將一個APK文件寫入會話
//指定有效長度系統將預先分配底層磁盤空間以優化磁盤上的放置
out = session.openWrite("app_store_session", 0, sizeBytes);
int total = 0;
byte[] buffer = new byte[65536];
int len;
while ((len= in.read(buffer)) != -1) {
total += len;
out.write(buffer, 0, len);
}
//根據需要調用,用來確保字節已保留到磁盤
session.fsync(out);
in.close();
out.close();
Log.d(TAG,"InstallApkViaPackageInstaller - Success: streamed apk " + total + " bytes");
PendingIntent broadCastTest = PendingIntent.getBroadcast(
context,
sessionId,
new Intent(ACTION_INSTALL_COMPLETE),
PendingIntent.FLAG_UPDATE_CURRENT);
//提交之前必須關閉所有流
session.commit(broadCastTest.getIntentSender());
session.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
由於apk須放置在你執行的APP下,因此要在執行的app建立assets,複製到/data/data/< package name >/files/…
做法如下;
private void copyAssets(Context context) {
Log.d(TAG, "Do copyAssets");
AssetManager assetManager = context.getAssets();
String[] files = null;
try {
files = assetManager.list("");
} catch (IOException e) {
Log.e(TAG, "Failed to get asset file list.", e);
}
if (files != null) for (String filename : files) {
InputStream in = null;
OutputStream out = null;
try {
Log.d(TAG, "Copy " + filename + "......");
in = assetManager.open(filename);
//File outFile = new File(context.getExternalFilesDir(null), filename);
//File outFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/", filename);
File outFile = new File(context.getFilesDir(), filename);
Log.d(TAG, "outFile:" + outFile);
out = new FileOutputStream(outFile);
copyFile(in, out);
} catch(IOException e) {
Log.e(TAG, "Failed to copy asset file: " + filename, e);
}
finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
// NOOP
}
}
if (out != null) {
try {
out.close();
} catch (IOException e) {
// NOOP
}
}
}
}
Log.d(TAG, "Finished copyAssets");
}
private void copyFile(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[1024];
int read;
while((read = in.read(buffer)) != -1){
out.write(buffer, 0, read);
}
}
Place your comment