2013-01-16 10 views
10

ユーザーがブラウザでファイルをダウンロードすると、Android 4.2がダウンロードされます。ユーザーが「ダウンロード完了」通知をクリックすると、インテントはいつでも起動していました。アンドロイド4.2コンテンツでダウンロードしたファイルのパスを持っていた意図する前に、よう:捕捉されたDownloadManagerインテントからファイルパスを取得する

intent.getData() 

は、file:///storage/emulated/0/Download/some_file.extとして文字列を返します。しかし、Android 4.2以来、ダウンロードマネージャはcontent://downloads/all_downloads/2334のようなcontent体系で放送し、意図しています。

ダウンロードしたファイルのローカルファイルパスを取得するにはどうすればよいですか?

私は次のことを試してみた:

public static String getRealPathFromURI(Uri contentUri, Activity activity) { 
    DownloadManager downloadManager = (DownloadManager) activity.getSystemService(Activity.DOWNLOAD_SERVICE); 
    String[] contentParts = contentUri.getEncodedPath().split("/"); 
    Cursor q = downloadManager.query(new DownloadManager.Query().setFilterById(Integer.parseInt(contentParts[contentParts.length - 1]))); 
    if (q == null) { 
     // Download no longer exists 
     return null; 
    } 
    q.moveToFirst(); 
    return q.getString(q.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME)); 
} 

をしかし、カーソルが(そうq.getCount() == 0及びそのための最後のreturn文が例外をスロー)任意の行を返すことはありません。また、ダウンロードファイルIDをUriから解析することによるハックは奇妙に思えます。

UPDATE:私も試してみました:

input = getActivity().getContentResolver().openInputStream(contentUri); 

をしかし、これは

許可拒否を示すエラーを返します:読んcom.android.providers.downloads.DownloadProvider URIコンテンツを://downloads/all_downloads/2334 from pid = 30950、uid = 10064にはandroid.permission.ACCESS_ALL_DOWNLOADS、またはgrantUriPermission()が必要です

明らかに私はダウンロードにアクセスできません(私のアプリはブラウザを起動しなかったので)ContentProviderでダウンロードできます。

+0

ところで、あなたの最初のアプローチはDownloadManager.COLUMN_STATUS == STATUS_SUCCESSFULとで有効なURIを返す、私のために動作しますオールライト列COLUMN_LOCAL_URI。 – southerton

答えて

1

コンテンツリゾルバを経由することは正しいことです。すべてのコンテンツURLがファイルになるわけではありません。たとえば、Galleryアプリケーションは、ソースに応じてネットワークコールまたはローカルファイルに変換するuriを提供します。

実際のファイルパスになっても、ファイルのアクセス権のためにそのファイルを読み取ることはできませんが、外部ストレージに置いても大丈夫です。 例外のように、あなたのアプリにandroid.permission.ACCESS_ALL_DOWNLOADSを追加しようとしましたか?That won't work, since the permission is at signature level :(

+0

はい、ContentResolverを経由する必要があると思いますが、上記の問題があります。そして、はい、 ''は私のAndroidManifest.xmlファイルにありますが、あなたがこの許可を求めているとは確信していません... –

+0

シンプルなテストアプリと私のためにうまくいった。この例外は、ダウンロードアプリケーションでファイルがクリックされた場合に付与された読み取り権限を何らかの形で「失った」ことを意味します。 – botteaap

5

これはうまくいきました。まず、ボットマップが正しく指摘されているため、ファイルパスを取得することはできません。

InputStream input = getContentResolver().openInputStream(intent.getData()); 

あなたはJavaで他と同様に、このInputStreamを読むことができます:(。正しい道に私を設定するために彼のクレジット)が代わりにあなたが使用して、ファイルのコンテンツにアクセスするために自動的に一時的な許可を取得します。ファイル名を取得する方法がないようです。ファイルが必要な場合は、まず入力ストリームを(一時的な)ファイルに書き込みます。

SecurityExceptionは、一時的なアクセスが取り消されたときにスローされます。これは私が前に間違って、特に意図が私のActicityのonNewIntentでピックアップされたときに、間違って読むことを試みたいくつかのファイルで私にとって起こりました。

+1

カーソルを使用して名前とサイズを取得できますが、URL全体は取得できません。名前を取得することをお勧めします。同じ名前とファイル拡張子を持つテンポラリファイルを保存することができます – jcesarmobile

+0

'onNewIntent'で' SecurityException'を避ける方法を見つけましたか?私は同じ問題を抱えており、それについて何をすべきか分かりません。 –

+0

@Jarett私は自分のアクティビティの起動モードを変更しても、この問題は発生していません。おそらく、それはsingleInstance(私はsingleTopを現在使用しています)に関係しているのでしょう。なぜなら、アクティビティはonNewIntentで得られたインテントを常に得るからです。申し訳ありませんが、私はより多くの情報を持っていません。 –

2

これを理解するまでに数時間かかりましたので、@erickokの回答に追加したいだけです。 @jcesarmobileで述べたように、フルパスではなくファイルの名前とサイズを取得できることが保証されています。

あなたは次のように名前とサイズを取得した後、一時ファイルに保存することができます:

String filename = null; 
Long filesize = null; 
Cursor cursor = null; 
try { 
    cursor = this.getContentResolver().query(intent.getData(), new String[] { 
     OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE}, null, null, null); 
    if (cursor != null && cursor.moveToFirst()) { 
     filename = cursor.getString(0); 
     filesize = cursor.getLong(1); 
    } 
} finally { 
    if (cursor != null) 
     cursor.close(); 
} 
+0

これはファイル名ではなく、DownloadManager.Request setTitleメソッドに割り当てられたタイトルです。 – southerton

関連する問題