【问题标题】:Can't install apk from uri on Android 10 in Eclipse projects无法在 Eclipse 项目中的 Android 10 上从 uri 安装 apk
【发布时间】:2021-05-26 09:32:51
【问题描述】:

我们正在从文件 uri 安装 apk,它可以在 Android Pie(9) 上运行,在 Android 10 移动版中它显示 “解析时出现问题”。我们仅将文件存储在应用程序存储中,构建版本为 4.4

我已经分享了下面的代码。

String PATH = Objects.requireNonNull(this.myActivity.getExternalFilesDir(null)).getAbsolutePath();
                 File file = new File(PATH + "/"+Utils.apk_name);
                 intent = new Intent("android.intent.action.VIEW");
                 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                 Uri uri = FileProvider.getUriForFile(this.myActivity, this.myActivity.getApplicationContext().getPackageName() + ".provider", file);
                 //Intrinsics.checkExpressionValueIsNotNull(uri, "FileProvider.getUriForFi…eProvider.install\", file)");
                 intent.setDataAndType(uri, "application/vnd.android.package-archive");
startActivity(intent);

清单中的提供者

<provider
        android:name="com.kirubha.helpers.ESEProvider"          
        android:authorities="com.kirubha.provider" 
        android:exported="false"
        android:grantUriPermissions="true">
            <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/provider_paths" />
    </provider>

provider_paths

<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path
    name="external_storage_root"
    path="."/>
</paths>

【问题讨论】:

  • ESEProvider 和 FileProvider 有什么关系?
  • &lt;external-path for getExternalFilesDir() 你应该使用&lt;external-files-path
  • 而且...有趣...您仍在使用 Eclipse!
  • ACTION_VIEW 已弃用应用安装。 gitlab.com/commonsguy/cw-android-q/-/tree/vFINAL/AppInstaller 展示了如何使用PackageInstaller,这是更长期的解决方案。

标签: java android cordova


【解决方案1】:

我发现当我添加文件时,我对文件提供者的大部分担忧都消失了

StrictMode.VmPolicy.Builder buildervm = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(buildervm.build());

我的主要活动。

在这个答案中找到了上述内容,可能对您有用。

android.os.FileUriExposedException: file:///storage/emulated/0/test.txt exposed beyond app through Intent.getData()

【讨论】:

  • 你不应该建议这种讨厌的技巧,而是传播和编写普通代码。
【解决方案2】:

在 Android 10 中,ACTION_VIEW 已弃用,需要改用 PackageInstaller。

按照下面的代码在Java中实现PackageInstaller

private static int REQUEST_OEN_DOCUMENT = 1337;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                            Intent intent1 = new Intent(Intent.ACTION_OPEN_DOCUMENT);
                            intent1.setType("application/vnd.android.package-archive");
                            intent1.addCategory(Intent.CATEGORY_OPENABLE);
                            startActivityForResult(intent1, REQUEST_OPEN_DOCUMENT);
                        }

此代码将重定向到文件夹。然后需要选择.apk文件。

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUEST_OEN_DOCUMENT) {
            if (resultCode == Activity.RESULT_OK) {
                if (data != null) {
                    Uri uri = data.getData();

                   installAfterQ(uri);

                }
            }
        }

    }


public void installAfterQ(Uri uri) {
        try {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                InputStream inputStream = getApplication().getContentResolver().openInputStream(uri);

                long length = DocumentFile.fromSingleUri(getApplication(), uri).length();
                PackageInstaller installer = getApplication().getPackageManager().getPackageInstaller();
                PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL);
                int sessionId = installer.createSession(params);
                PackageInstaller.Session session = installer.openSession(sessionId);

                File file = new File(uri.getPath());
                OutputStream outputStream = session.openWrite(file.getName(), 0, length);

                byte[] buf = new byte[1024];
                int len;
                while ((len = inputStream.read(buf)) > 0) {
                    outputStream.write(buf, 0, (int) len);
                }


                session.fsync(outputStream);

                outputStream.close();
                inputStream.close();

                Intent intent = new Intent(getApplication(), UpdateReceiver.class);
                PendingIntent pi = PendingIntent.getBroadcast(getApplication(), 3439, intent, PendingIntent.FLAG_UPDATE_CURRENT);
                session.commit(pi.getIntentSender());
                session.close();
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

更新接收器类:

public class UpdateReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {

int status = intent.getIntExtra(PackageInstaller.EXTRA_STATUS, -1);

if (status == PackageInstaller.STATUS_PENDING_USER_ACTION) {
Intent activityIntent =intent.getParcelableExtra(Intent.EXTRA_INTENT);
    context.startActivity(activityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
} else if (status == PackageInstaller.STATUS_SUCCESS) {
    Toast.makeText(context, "Successfully Installed", Toast.LENGTH_SHORT).show();
} else {

     String msg =intent.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE);
    Toast.makeText(context, "Error while installing" + msg, Toast.LENGTH_SHORT).show();

}


    }
}

Android Manifest.xml

在应用程序标签内。

<receiver android:name=".UpdateReceiver"/>

        <meta-data
            android:name="com.android.packageinstaller.notification.smallIcon"
            android:resource="@drawable/ic_install_notification" />

权限:

<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />

试试这个代码。希望此代码对您有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-23
    相关资源
    最近更新 更多