Android N、例外が発生します。これはドキュメントによる既知の問題であり、ContentResolver.openFileDescriptor()を使用するように求められます。
https://developer.Android.com/reference/Android/app/DownloadManager.html#COLUMN_LOCAL_FILENAME
使い方がわかりません。ファイル名を取得するために使用できるContentResolverオブジェクトはどこにありますか?私はそれを使ったことがありません。だから、私はどんな助けにも感謝します。
08-04 11:20:59.765 7010 7290 W System.err:Java.lang.SecurityException:COLUMN_LOCAL_FILENAMEは非推奨です。代わりにContentResolver.openFileDescriptor()を使用してください
08-04 11:20:59.765 7010 7290 W System.err:Android.app.DownloadManager $ CursorTranslator.getString(DownloadManager.Java:1499)
これが私のコードです。
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(id);
Cursor cursor = downloadManager.query(query);
final String downloadFilePath = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME));
cursor.close();
DownlaodManager.getFileUriを試しましたが、探しているものではありません。助けに感謝します。
ありがとう
以下は私のために今働いています:
String downloadFilePath = null;
String downloadFileLocalUri = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
if (downloadFileLocalUri != null) {
File mFile = new File(Uri.parse(downloadFileLocalUri).getPath());
downloadFilePath = mFile.getAbsolutePath();
}
私はこの問題を使用して解決します _DownloadManager.COLUMN_LOCAL_URI
_ 代わりに _DownloadManager.COLUMN_LOCAL_FILENAME
_
DownloadManager.COLUMN_LOCAL_URIは、「file://」を含むファイルパスを返すため、downloadFilePath = downloadFilePath.replace("file://","");
を使用してdownloadFilePath
から除外する必要があります。
この問題の1行の解決策は次のとおりです。
_String downloadFilePath = (c.getString(c.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI))).replace("file://","");
_
DownloadManagerの完全なコードを以下で確認してください。
DownloadFinishedReceiver.Java
_public class DownloadFinishedReceiver extends BroadcastReceiver {
@Override
public void onReceive(final Context context, Intent intent) {
String action = intent.getAction();
if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action) && intent.getExtras()!=null) {
Bundle extras = intent.getExtras();
DownloadManager.Query q = new DownloadManager.Query();
long downloadId = extras.getLong(DownloadManager.EXTRA_DOWNLOAD_ID);
q.setFilterById(downloadId);
Cursor c = ((DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE)).query(q);
if (c.moveToFirst()) {
int status = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));
if (status == DownloadManager.STATUS_SUCCESSFUL) {
String downloadFilePath = (c.getString(c.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI))).replace("file://","");
String downloadTitle = c.getString(c.getColumnIndex(DownloadManager.COLUMN_TITLE));
c.close();
Log.e("DownloadPath", downloadFilePath); // Print DownloadPath in Logcat
Log.e("DownloadTitle", downloadTitle); // Print DownloadTitle in Logcat
} else if (status == DownloadManager.STATUS_FAILED) {
removeTempOnFailure(context, downloadId);
}
}
}
}
// Remove temp/cache data
private void removeTempOnFailure(Context con, long downloadId) {
File cacheFileDir = new File(con.getCacheDir().getAbsolutePath());
for (File f : cacheFileDir.listFiles()) {
if (f.getName().contains(String.valueOf(downloadId))) {
f.delete();
break;
}
}
}
}
_
BroadcastReceiverをAndroidMenifest.xmlファイルに登録します。
_ <receiver
Android:name="com.example.receiver.DownloadFinishedReceiver"
Android:exported="true"
Android:process=".downloadFinished">
<intent-filter>
<action Android:name="Android.intent.action.DOWNLOAD_COMPLETE" />
</intent-filter>
</receiver>
_
以下のメソッドをActivityに入れて、適切な引数を渡します。
_ /**
*
* @param downloadUrl -> Your file download url
* @param downloadTitle -> Your file title to display in download manager
* @param fileName -> filename with extension like music.mp3 it will store in download folder
* @param hide -> true to hide downloadmanager in status bar, false to display it
* @return -> it will return downloadId
*/
private long downloadFromUrl(String downloadUrl, String downloadTitle, String fileName, boolean hide) {
Uri uri = Uri.parse(downloadUrl);
DownloadManager.Request request = new DownloadManager.Request(uri);
request.setTitle(downloadTitle);
if (hide) {
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN);
request.setVisibleInDownloadsUi(false);
} else
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName);
DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
return manager != null ? manager.enqueue(request) : 0;
}
_
上記のメソッドでhide = trueを渡す場合は、_AndroidManifext.xml
_に次の権限を追加する必要があります
_<uses-permission Android:name="Android.permission.DOWNLOAD_WITHOUT_NOTIFICATION"/>
_
getUriForDownloadedFile
を使用して、ダウンロードしたUriを取得します。
DownloadManager downloadManager = DownloadManager.class.cast(getSystemService(DOWNLOAD_SERVICE));
Uri uri = downloadManager.getUriForDownloadedFile(id);
commonsWareが指摘したように、ファイルURIを常に取得しているわけではなく、コンテンツURIを取得していることが多いため、techtinkererの回答も機能しませんでした。ただし、コンテンツURIからファイルを取得する方法はいくつかあります。
1)getContentResolver()。openInputStream(myContentUri)を呼び出して入力ストリームを取得し、外部ストレージまたは内部ストレージに作成したファイルに書き込むことができます。
2)getContentResolver()。openFileDescriptor(myContentUri、 "r")を呼び出して、読み取り専用のParcelFileDescriptorを開くことができます。 ParcelFileDescriptorから絶対ファイルパスを取得することはできませんが、ファイルまたはURIを受け入れる多くのメソッドはParcelFileDescriptorも受け入れます。
たとえば、DownloadManagerを使用してPDFをダウンロードし、コンストラクターがParcelFileDescriptorを受け入れるPdfRendererで開きます。
PdfRenderer renderer;
ParcelFileDescriptor pdfFileDescriptor = getContentResolver().openFileDescriptor(pdfUri, "r");
if (pdfFileDescriptor != null) renderer = new PdfRenderer(pdfFileDescriptor);
pdfFileDescriptor.close();
別の例として、BitmapFactoryにはParcelFileDescriptorをデコードするメソッドもあります。
( https://developer.Android.com/guide/topics/providers/document-provider.html から)
private Bitmap getBitmapFromUri(Uri uri) throws IOException {
ParcelFileDescriptor parcelFileDescriptor =
getContentResolver().openFileDescriptor(uri, "r");
FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor);
parcelFileDescriptor.close();
return image;
}
したがって、実行する内容によっては、ParcelFileDescriptorだけで十分な場合があります。
GradleでtargetSdkを24未満に減らすことができます。実際、このアプローチは推奨されるアプローチではありませんが、ターゲットSDK 23など(ただし24未満)を減らすことでこのエラーを克服できます。
私は使用しなければなりませんでした_DownloadManager.COLUMN_URI
_
_DownloadManager.COLUMN_LOCAL_URI
_の代わりに
c.getString(c.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI))
->content:// downloads/my_downloads/46
c.getString(c.getColumnIndex(DownloadManager.COLUMN_URI))
->http://test-domain.com/files/encrypted/212125/bsd1e-411cd7-e3229fb-fdddsa12a974.pdf
c.getString(c.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME))
->http://test-domain.com/files/encrypted/212125/bsd1e-411cd7-e3229fb-fdddsa12a974.pdf
String downloadFileLocalUri = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
上記の方法により、 CursorIndexOutOfBoundsException 行のリストが空の場合。
カーソルは、最初のエントリの前に配置されるオブジェクトです。したがって、最初に結果があるかどうかを確認する必要があります。これが私の例です:
int index = cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI);
if (cursor.moveToFirst()) {
String downloadFileLocalUri = cursor.getString(index);
if (downloadFileLocalUri != null) {
File mFile = new File(downloadFileLocalUri);
downloadFileName = mFile.getName();
downloadFilePath = mFile.getAbsolutePath();
}
}
cursor.close();