[英]Issue installing .apk with PackageInstaller
我的目标是安装存储在设备上的 .apk 文件。 我尝试使用 ACTION_VIEW 意图,但我相信它从 Android 10 开始被弃用。
我已经搜索了 web 的一半,但大多数答案要么使用已弃用的意图 kotlin,要么根本不起作用。
这是我的代码
private void installApk() throws IOException {
if (!requireContext().getPackageManager().canRequestPackageInstalls()) {
startActivity(new Intent(
Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES,
Uri.parse("package:" + requireContext().getPackageName())));
} else {
// Log.d(TAG, "File Exists?: " + outputFile.exists() + " ; " + outputFile.getAbsolutePath() + " ; " + "can read?" + outputFile.canRead() + " ; " + "can write?" + outputFile.canWrite());
PackageInstaller packageInstaller = requireContext().getPackageManager().getPackageInstaller();
PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(PackageInstaller
.SessionParams.MODE_FULL_INSTALL);
int sessionId = packageInstaller.createSession(params);
PackageInstaller.Session session = packageInstaller.openSession(sessionId);
addApkToInstallSession(session);
Intent callbackIntent = new Intent(requireContext(), APKInstallService.class);
PendingIntent pendingIntent = PendingIntent.getService(requireContext(), 0, callbackIntent, 0);
// This is sending the result of the installation to the APKInstallService.
IntentSender statusReceiver = pendingIntent.getIntentSender();
session.commit(statusReceiver);
}
}
这是我在 onClickListener 中调用的方法
private void addApkToInstallSession(PackageInstaller.Session session)
throws IOException {
try (OutputStream packageInSession = session.openWrite("package", 0, -1);
InputStream is = requireContext().getContentResolver().openInputStream(fileURI)) {
byte[] buffer = new byte[16384];
int n;
while ((n = is.read(buffer)) >= 0) {
packageInSession.write(buffer, 0, n);
}
}
}
将文件添加到 session。
import android.app.Service;
import android.content.Intent;
import android.content.pm.PackageInstaller;
import android.os.IBinder;
import android.util.Log;
import androidx.annotation.Nullable;
public class APKInstallService extends Service {
private static final String TAG = "APKInstallService";
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
int status = intent.getIntExtra(PackageInstaller.EXTRA_STATUS, -999);
switch (status) {
case PackageInstaller.STATUS_PENDING_USER_ACTION:
Log.d(TAG, "Requesting user confirmation for installation");
// This is a way to get the intent that was passed to the service.
//Intent confirmationIntent = intent.getParcelableExtra(Intent.EXTRA_INTENT);
//confirmationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//try {
// startActivity(confirmationIntent);
//} catch (Exception e) {
//No action
// }
break;
case PackageInstaller.STATUS_SUCCESS:
Log.d(TAG, "Installation succeed");
break;
default:
Log.d(TAG, "Installation failed");
break;
}
stopSelf();
return START_NOT_STICKY;
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
得到结果
我对编码很陌生,如果这是一个愚蠢的问题,我很抱歉
看起来问题在于我的模拟器没有安装 gapps,即使没有在任何地方说明,这显然是对此类操作的依赖。 尽管我会推荐 CommonsWare 在他的评论中提出的章节,因为它们比稀缺文档要全面得多。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.