序文:
私たちのアプリはカスタマイズされたパッドなので、システムによって署名されていますが、サイレントインストールに適したものを見つけるために長い間探していました、そしてそれがコードです
まずはAPKのダウンロード方法です
// 文件保存路径
private String mSavePath;
// 版本名称
private String mVersion_name = "/名称.apk";
/*
* 开启新线程下载apk文件
*/
private void downloadAPK(String mUrl) {
new Thread(new Runnable() {
@Override
public void run() {
try {
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
String sdPath = Environment.getExternalStorageDirectory() + "/";
// 文件保存路径
// mSavePath = sdPath + "jikedownload";
mSavePath = "/data/user/0/包名/files";
// mSavePath = "/data/local/tmp/";
File dir = new File(mSavePath);
if (!dir.exists()) {
dir.mkdir();
}
// 下载文件
HttpURLConnection conn = (HttpURLConnection) new URL(mUrl).openConnection();
conn.connect();
InputStream is = conn.getInputStream();
int length = conn.getContentLength();
File apkFile = new File(mSavePath, mVersion_name);
FileOutputStream fos = new FileOutputStream(apkFile);
int count = 0;
byte[] buffer = new byte[1024];
while (!mIsCancel) {
int numread = is.read(buffer);
count += numread;
// 计算进度条的当前位置
mProgress = (int) (((float) count / length) * 100);
Log.e("Base", "下载进度" + mProgress);
// 下载完成
if (numread < 0) {
Log.e("Base", "下载完成");
// mUpdateProgressHandler.sendEmptyMessage(2);
//静默安装
StringBuilder append = new StringBuilder().append(mSavePath).append(mVersion_name);
boolean installResult = Install.silentInstallApk(mContext,append.toString());
Log.e("Base", "安装结果" + installResult);
// break;
}
fos.write(buffer, 0, numread);
}
fos.close();
is.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
次に、サイレントインストール用のコードがあります
/**
* 静默安装
*/
public class Install {
private final static SynchronousQueue<Intent> mInstallResults = new
SynchronousQueue<>();
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public static synchronized boolean silentInstallApk(Context context,
final String apkFilePath) {
boolean ret = false;
File apkFile = new File(apkFilePath);
PackageInstaller installer = context.getPackageManager().getPackageInstaller();
PackageInstaller.SessionParams sessionParams = new
PackageInstaller.SessionParams(
PackageInstaller.SessionParams.MODE_FULL_INSTALL);
sessionParams.setSize(apkFile.length());
int sessionId = createSession(installer, sessionParams);
if (sessionId != -1) {
boolean isCopyOk = copyInstallApkFile(sessionId, installer, apkFilePath);
if (isCopyOk) {
boolean isInstalled = installPackage(context, sessionId,
installer, apkFilePath);
if (isInstalled) {
ret = true;
}
}
}
return ret;
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private static int createSession(PackageInstaller installer,
PackageInstaller.SessionParams sessionParams) {
int sessionId = -1;
try {
sessionId = installer.createSession(sessionParams);
} catch (IOException e) {
e.printStackTrace();
}
return sessionId;
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private static boolean copyInstallApkFile(int sessionId, PackageInstaller installer,
String apkFilePath) {
InputStream in = null;
OutputStream out = null;
PackageInstaller.Session session = null;
boolean ret = false;
try {
File apkFile = new File(apkFilePath);
session = installer.openSession(sessionId);
out = session.openWrite("base.apk", 0, apkFile.length());
in = new FileInputStream(apkFile);
File file = new File(String.valueOf(apkFile));
if (file.exists()) {
Log.i("Base", "存在");
}
int count;
byte[] buffer = new byte[65536];
while ((count = in.read(buffer)) != -1) {
out.write(buffer, 0, count);
}
session.fsync(out);
ret = true;
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if (in != null) {
in.close();
}
} catch (IOException e) {
e.printStackTrace();
}
session.close();
}
return ret;
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private static boolean installPackage(Context context, int sessionId,
PackageInstaller installer, String filePath) {
PackageInstaller.Session session = null;
boolean ret = false;
try {
session = installer.openSession(sessionId);
Intent intent = new Intent();
intent.setAction("com.example.install");
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 1, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
session.commit(pendingIntent.getIntentSender());
final Intent intentResult = mInstallResults.poll(60, TimeUnit.SECONDS);
//这个地方返回的*intentResult *为null,所以导致代用静默安装方法返回的值为**false**,但是app已经成功静默安装成功了,至于原因
//笔者也暂时没有找到,如果有哪位看官懂,麻烦评论下,感谢
if (intentResult != null) {
final int status = intentResult.getIntExtra(PackageInstaller.EXTRA_STATUS,
PackageInstaller.STATUS_FAILURE);
if (status == PackageInstaller.STATUS_SUCCESS) {
ret = true;
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
session.close();
}
return ret;
}
}
最後に忘れてはならないのが権限です。
<uses-permission android:name="android.permission.INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.BIND_DEVICE_ADMIN" />
これがすべてのコードです。宣言したい点がいくつかあります。1 つ目は、APK のアドレスと APK の名前を配置することです。これは自分で変更する必要があります。2 つ目は、サイレント メソッドを呼び出した後の戻り値です。実際にインストールすると false が返されますが、アプリはサイレントで正常にインストールされました。理由については、中断ポイントの具体的な理由が見つかりませんでした。理解できる方がいらっしゃいましたら、コメントしてください。ありがとうございます。最後に、上記は私自身の経験とインターネット上の記事を参考にした私の結論です。以下を参照してください。