简体   繁体   English

使用 PackageInstaller 发出 installing.apk

[英]Issue installing .apk with PackageInstaller

My goal is to install an.apk file that's stored on the device.我的目标是安装存储在设备上的 .apk 文件。 I tried using ACTION_VIEW intent, but it's deprecated as of Android 10, I believe.我尝试使用 ACTION_VIEW 意图,但我相信它从 Android 10 开始被弃用。

I've already scoured half the web, but most answers are either using the deprecated intents, kotlin or just don't work.我已经搜索了 web 的一半,但大多数答案要么使用已弃用的意图 kotlin,要么根本不起作用。

Here's my code这是我的代码

 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);


        }
    }

This is the method I call in my onClickListener这是我在 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);
            }
        }
    }

Adding the file to the session.将文件添加到 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;
    }
}

Getting the result得到结果

I'm fairly new to coding, so sorry if this is a dumb issue我对编码很陌生,如果这是一个愚蠢的问题,我很抱歉

It looks like the issue was in the fact that my emulator didn't have gapps installed, which is, even though not stated anywhere, apparently a dependency for this kind of action.看起来问题在于我的模拟器没有安装 gapps,即使没有在任何地方说明,这显然是对此类操作的依赖。 Although I would recommend the chapters that CommonsWare brought up in his comment, as they were much more comprehensive than the scarce documentation.尽管我会推荐 CommonsWare 在他的评论中提出的章节,因为它们比稀缺文档要全面得多。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM