web-dev-qa-db-ja.com

Android Intent.VIEW_ACTIONでapkをインストールし、ファイルプロバイダーで動作しない

私のアプリには、APKをダウンロードする自動更新機能があり、ダウンロードが完了すると、Intent.VIEW_ACTIONでアプリを開き、ユーザーがダウンロードしたapkをインストールできるようにします

         Uri uri = Uri.parse("file://" + destination);
         Intent install = new Intent(Intent.ACTION_VIEW);
        install.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        install.setDataAndType(uri,
            manager.getMimeTypeForDownloadedFile(downloadId));
        activity.startActivity(install);

これは、すべてのデバイス<24

Android 24では、file:///でインテントを開始することは許可されていないようです。グーグルで調べた後、ファイルプロバイダーを使用することをお勧めしました。

新しいコード:

Intent install = new Intent(Intent.ACTION_VIEW);
    install.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    install.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    Uri apkUri = FileProvider.getUriForFile(AutoUpdate.this,
        BuildConfig.APPLICATION_ID + ".provider", file);
    install.setDataAndType(apkUri,
        manager.getMimeTypeForDownloadedFile(downloadId));
    activity.startActivity(install);

今すぐactivity.startActivity(install);エラーを投げる

インテントを処理するアクティビティが見つかりません{act = Android.intent.action.VIEW dat = content://com.xxxx.xx.provider/MyFolder/Download/MyApkFile.apk typ = application/vnd.Android.package-archive flg = 0x4000000}

Android 7(24)でAPKビューアーを開く方法はありますか?

57
Johny19

たくさんの試みの後、Nougatがエラーを引き起こす前にAndroidバージョンでFileProviderを使用してインストールインテントを作成するように、Nougatより低いものに異なるインテントを作成することでこれを解決できました。

ActivityNotFoundException: No Activity found to handle Intent { act=Android.intent.action.INSTALL_PACKAGE dat=content://XXX.apk flg=0x1 }

Android Nougatで通常のUriを使用すると、次のエラーが作成されます。

FileUriExposedException: file:///XXX.apk exposed beyond app through Intent.getData()

エミュレータでAndroid NとAndroid Mを実行している電話で動作する私のソリューション.

File toInstall = new File(appDirectory, appName + ".apk");
Intent intent;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    Uri apkUri = FileProvider.getUriForFile(activity, BuildConfig.APPLICATION_ID + ".fileprovider", toInstall);
    intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
    intent.setData(apkUri);
    intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
} else {
    Uri apkUri = Uri.fromFile(toInstall);
    intent = new Intent(Intent.ACTION_VIEW);
    intent.setDataAndType(apkUri, "application/vnd.Android.package-archive");
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
activity.startActivity(intent);

Android Nougat 7.1のアップデート:

マニフェストに権限REQUEST_INSTALL_PACKAGESを追加する必要もあります。 Api Level 23(Android 6.0 Marshmallow)から利用可能で、Level 25(Android 7.1 Nougat)から必要です。

更新:

インストールしようとするファイルが外部ストレージにある場合は、外部ストレージへの読み取りと書き込みの許可を忘れずに要求してください。また、Android Nougat以上の正しいFileProviderを設定することもできます。

まずcanReadWriteExternal()を呼び出して書き込み許可を持っているかどうかを確認し、そうでない場合はrequestPermission()を呼び出します:

private static final int REQUEST_WRITE_PERMISSION = 786;

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    if (requestCode == REQUEST_WRITE_PERMISSION && grantResults[0] == PackageManager.PERMISSION_GRANTED)
        Toast.makeText(this, "Permission granted", Toast.LENGTH_LONG).show();
}

private void requestPermission() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
        requestPermissions(new String[]{ Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_WRITE_PERMISSION);
}

private boolean canReadWriteExternal() {
    return Build.VERSION.SDK_INT < Build.VERSION_CODES.M ||
            ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED;
}

外部ストレージのダウンロードフォルダーのファイルプロバイダーの例を次に示します。 AndroidManifest.xml

<application ... >
    ...

    <provider
        Android:name="Android.support.v4.content.FileProvider"
        Android:authorities="${applicationId}.fileprovider"
        Android:exported="false"
        Android:grantUriPermissions="true">
        <meta-data
            Android:name="Android.support.FILE_PROVIDER_PATHS"
            Android:resource="@xml/filepaths" />
    </provider>
</application>

resources/xml/filepaths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <external-path name="external_download" path="Download"/>
</paths>

.apkのインストール中に「パッケージの解析中に問題が発生しました」などのエラーが表示された場合。読み取り/書き込み権限を要求していないか、インストールしようとしているファイルが存在しないか破損している可能性があります。

133
just_user

これが問題になる可能性があります

intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 

あなたの例では

install.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

installはインテントの名前です。

6
Rob Francis

API <24の場合、以下を使用する必要があることに注意してください。

        setDataAndType(Uri.fromFile(apkFile), "application/vnd.Android.package-archive")

データとタイプを個別に設定する代わりに:

data = Uri.fromFile(apkFile)
    type = "application/vnd.Android.package-archive"

そうでない場合は、ActivityNotFoundExceptionが発生します

1
MohammadReza

開始アクティビティを呼び出すときにこの問題が発生しました。現在のアクティビティを一時停止した後、突然戻ってonResumeを呼び出しました。何も起こらなかったように。私の問題はマニフェストのこの許可にありました:

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

ほとんど誰もそれについて言及しませんでした。これを覚えておいてください。 SDK 24以上では、file:///から始まるインテントが必要であるため、プロバイダーを使用する必要があります。 @just_userが正しい答えを書いたので、このためのコードを書く必要はないと思います。

1
Hossein Karami