web-dev-qa-db-ja.com

PhoneGap Camera Pluginを使用してAndroid 4.4(KitKat))のギャラリーから選択すると、画像をロードできません

PhoneGap/Cordova Camera Pluginを使用して、デバイスイメージギャラリーから選択したイメージに基づいて、アプリでimgタグのソースを設定しようとしています。

以前は、Android(3.3))の古いバージョンで意図したとおりに機能し、iOSでは正常に動作しますが、4.4(KitKat)ではイメージパスの解決に失敗しました。

返される画像URLの返されるパスは次のようになります。

_content://com.Android.providers.media.documents/document/image%3A352
_

このパスを使用してJavaScriptを介して画像srcとして設定すると、URLを解決できないため、ロードエラーが発生します。カメラで写真を撮るときに問題はありません。ギャラリーから既存の写真を選択するときにのみ発生するようです。

Base64へのエンコードを試み、ドキュメントresolveLocalFileSystemURI();に記載されている方法も試しましたが、これらには運がありませんでした。カメラプラグインを削除してアプリを再構築しようとしましたが、喜びはありませんでした。

私の推測では、KitKatがギャラリーを処理する方法で何かが変更され、PhoneGap/Cameraプラグインはまだこれに対応するように更新されていません。

33
CrazyEraserUK

画像のURIエンコーディングでAndroid 4.4で何かが壊れました。

コルドバに対してバグがここに提出されました: https://issues.Apache.org/jira/browse/CB-5398

getPicture のドキュメントのAndroid Quicksセクションの下で、この問題について説明し、回避策(Stackプラグインの編集Javaコード。)

別の方法として、宛先タイプをDATA_URLに設定することも考えられます。

16
MBillau

このバグが修正されている間、本当に非常に汚い回避策の一種が私のために機能します。極端に必要な場合に使用:)

if (imageURI.substring(0,21)=="content://com.Android") {
  photo_split=imageURI.split("%3A");
  imageURI="content://media/external/images/media/"+photo_split[1];
}
19
Miguel Delgado

この問題の簡単な修正方法を次に示します。

これを置き換えます:

content://com.Android.providers.media.documents/document/image%3A352

これで:

content://com.Android.providers.media.documents/document/image%253A352

javaScriptを使用している場合、次のコードを使用できます。

var path = content://com.Android.providers.media.documents/document/image%3A352;
path = path.replace("%", "%25");

この手法は、URIを「:」に変更せずに、「%3A」をそのまま渡すように強制します。

4

アドビは、この問題が3.5.0で修正されることを保証します。 3.4では修正されていません。 3.5.0は5月中旬にリリースされる予定なので、それまで待ちます。

Adobeは、これはプラグインレベルで行うことができる変更ではないと主張しています。 Cordovaコードの基本的な変更でした。彼らがこの修正を思い付くまでに時間がかかったのは残念です。

更新:Cordova 3.5.0は5月9日にリリースされました。biaノードをダウンロードして、問題が実際に解決されたかどうかを確認できます。

4
MLU

「content:」などの特別な条件を、拡張機能を使用せずにさらにいくつかチェックするだけで、さらに堅牢になりません。また、アップロードする必要があるため、拡張子を検出しています。ファイルに拡張子がない場合は.jpg拡張子を作成します。

// Android 4.4 cordova workarounds ... returns new kind or URL for content from chooser
                //if (imageUrl.substring(0,21)=="content://com.Android") {
                if(imageUrl.indexOf('content://') != -1 && imageUrl.indexOf("%3A") != -1){
                    //"PlainFileUrl = content://com.Android.providers.media.documents/document/image%3A14",
                    photo_split=imageUrl.split("%3A");
                    imageUrl="content://media/external/images/media/"+photo_split[1];
                }
                // workaround end

                var fileName = imageUrl.substr(imageUrl.lastIndexOf('/') + 1);
                var extension;

                // check for content: protocol to make sure is not
                // a file with no extension
                if (imageUrl.indexOf('content://') != -1) {
                    if(imageUrl.lastIndexOf('.') > imageUrl.lastIndexOf('/')){
                        extension = imageUrl.substr(imageUrl.lastIndexOf('.') + 1);
                    }else{
                        extension = "jpg";
                        fileName = fileName + ".jpg";
                        LogService.log("Created File Extension jpg");
                    }
                } else {
                    if (imageUrl.lastIndexOf('.') == -1 || (imageUrl.lastIndexOf('.') < imageUrl.lastIndexOf('/')) ) {
                        extension = "invalid";
                    } else {
                        extension = imageUrl.substr(imageUrl.lastIndexOf('.') + 1);
                    }
                }
2

いくつかのuri<img src="uri" />に渡されるたびに、暗黙的にデコードされます

content://com.Android.providers.media.documents/document/image%3A9888(1)

content://com.Android.providers.media.documents/document/image:9888(2)

ただし、Intent.ACTION_OPEN_DOCUMENTまたはIntent.ACTION_GET_CONTENTから戻った後Androidは、(1)(2)ではありません。この場合、WebViewは予期してエラーを記録します。

Java.lang.SecurityException:許可の拒否:pid = 13163からcom.Android.providers.media.MediaDocumentsProvider uri content://com.Android.providers.media.documents/document/image:9888を読み取るには、uid = 10165にはAndroidが必要です。 permission.MANAGE_DOCUMENTS、またはgrantUriPermission()

または

コンテンツURLを開けません

コードスニペット

問題を解決するために必要なのは

    String uriToUseInWebView = transformForWebView(uri.toString());

    private String transformForWebView(String uri) {
        for (int i = 0; i < timesDecodingWebView(); i++)
            uri = uri.replace("%", Uri.encode("%"));
        return uri;
    }

    private int timesDecodingWebView() {
        if (Build.VERSION.RELEASE.equals("4.4.2")) {
            return 2;
        } else {
            return 1;
        }
    }

あなたのJavaコードでuriをHTML/JSに渡してから、(1)実際にロードされます。

4.4.2、4.4.4、5.0でテストしました。面白い部分は、Android 4.4.2がuriを内部で2回デコードすることです。

0
riwnodennyk