Androidのダウンロードマネージャーに関する小さな質問。私がそれを使って作業するのは初めてで、複数のファイルを正常にダウンロードして開きました。しかし、私の質問は、ダウンロードが完了したかどうかを確認する方法です。
状況は、PDFファイルをダウンロードして開くことです。通常、ファイルは非常に小さいので、開く前に完了します。開く前にダウンロードしてください。
ダウンロード方法:
Intent intent = getIntent();
DownloadManager downloadManager = (DownloadManager)getSystemService(DOWNLOAD_SERVICE);
Uri Download_Uri = Uri.parse(intent.getStringExtra("Document_href"));
DownloadManager.Request request = new DownloadManager.Request(Download_Uri);
//Restrict the types of networks over which this download may proceed.
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI | DownloadManager.Request.NETWORK_MOBILE);
//Set whether this download may proceed over a roaming connection.
request.setAllowedOverRoaming(false);
//Set the title of this download, to be displayed in notifications.
request.setTitle(intent.getStringExtra("Document_title"));
//Set the local destination for the downloaded file to a path within the application's external files directory
request.setDestinationInExternalFilesDir(this,Environment.DIRECTORY_DOWNLOADS,intent.getStringExtra("Document_title") + ".pdf");
//Enqueue a new download and same the referenceId
Long downloadReference = downloadManager.enqueue(request);
ファイルを開く方法
Uri uri = Uri.parse("content://com.app.applicationname/" + "/Download/" + intent.getStringExtra("Document_title") + ".pdf");
Intent target = new Intent(Intent.ACTION_VIEW);
target.setDataAndType(uri, "application/pdf");
target.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(target);
そのため、ファイルをダウンロードしてから開くまでのどこかで、ifステートメントを使用して、ファイルを続行するかファイルを待機するかを確認する必要があります。
ダウンロードが完了したときにダウンロードマネージャーによって送信されるブロードキャストインテントアクション。ダウンロードが完了したときにレシーバーを登録する必要があります。
受信機を登録するには
registerReceiver(onComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
およびBroadcastRecieverハンドラー
BroadcastReceiver onComplete=new BroadcastReceiver() {
public void onReceive(Context ctxt, Intent intent) {
// your code
}
};
AsyncTaskを作成して、大きなファイルのダウンロードを処理することもできます
ある種のダウンロードダイアログを作成して、通知領域にダウンロードを表示し、ファイルのオープンを処理します。
protected void openFile(String fileName) {
Intent install = new Intent(Intent.ACTION_VIEW);
install.setDataAndType(Uri.fromFile(new File(fileName)),"MIME-TYPE");
startActivity(install);
}
サンプルのリンクも確認できます
受け入れられた答えは完全に正しいわけではありません。 ACTION_DOWNLOAD_COMPLETEブロードキャストを受信しても、ダウンロードが完了したわけではありません。 ACTION_DOWNLOAD_COMPLETEは、ダウンロードが完了するとDownloadManagerによってブロードキャストされることに注意してください。必ずしもあなたが待っているのと同じダウンロードであることを意味するわけではありません
解決策は、ダウンロードの開始時にenqueue()によって返されたダウンロードIDを保存することです。この長いダウンロードIDはシステム全体で一意であり、ダウンロードステータスの確認に使用できます
DownloadManager downloadManager= (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
long downloadID = downloadManager.enqueue(request);// enqueue puts the download request in the queue.
ダウンロードが完了すると、次の3つの手順で通知を受けることができます
下記のスニペットに示すようにBroadcastReceiverを作成します。受信側では、受信したダウンロードIDとエンキューされたダウンロードを照合することで、受信したブロードキャストがダウンロード用かどうかを確認します。
private BroadcastReceiver onDownloadComplete = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
//Fetching the download id received with the broadcast
long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
//Checking if the received broadcast is for our enqueued download by matching download id
if (downloadID == id) {
Toast.makeText(MainActivity.this, "Download Completed", Toast.LENGTH_SHORT).show();
}
}
};
BroadcastReceiverが作成されたら、アクティビティのonCreateメソッドでACTION_DOWNLOAD_COMPLETEに登録できます。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
registerReceiver(onDownloadComplete,new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
}
OnDestroyでBroadcastReceiverの登録を解除することも重要です。これにより、アクティビティがアクティブである限り、このブロードキャストのみを聞くことができます。
@Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(onDownloadComplete);
}
完全な例を読むことをお勧めします here
1週間以上、DownloadManagerを使用してファイルをダウンロードして開く方法の調査に費やしましたが、私にとって完全に完璧な答えを見つけることはできませんでした。できる限りコードを文書化するようにしました。質問がある場合は、回答の下のコメントに自由に質問を残してください。
また、この行をAndroidManifest.xmlファイルに追加することを忘れないでください!!
_<uses-permission Android:name="Android.permission.WRITE_EXTERNAL_STORAGE"/>
_
私のダウンロードマネージャー:
_import Android.app.DownloadManager;
import Android.content.ActivityNotFoundException;
import Android.content.BroadcastReceiver;
import Android.content.Context;
import Android.content.Intent;
import Android.content.IntentFilter;
import Android.net.Uri;
import Android.os.Environment;
import Android.webkit.CookieManager;
import Android.webkit.DownloadListener;
import Android.widget.Toast;
import Java.util.regex.Matcher;
import Java.util.regex.Pattern;
public class MyDownloadListener implements DownloadListener {
private Context mContext;
private DownloadManager mDownloadManager;
private long mDownloadedFileID;
private DownloadManager.Request mRequest;
public MyDownloadListener(Context context) {
mContext = context;
mDownloadManager = (DownloadManager) mContext
.getSystemService(Context.DOWNLOAD_SERVICE);
}
@Override
public void onDownloadStart(String url, String userAgent, String
contentDisposition, final String mimetype, long contentLength) {
// Function is called once download completes.
BroadcastReceiver onComplete = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// Prevents the occasional unintentional call. I needed this.
if (mDownloadedFileID == -1)
return;
Intent fileIntent = new Intent(Intent.ACTION_VIEW);
// Grabs the Uri for the file that was downloaded.
Uri mostRecentDownload =
mDownloadManager.getUriForDownloadedFile(mDownloadedFileID);
// DownloadManager stores the Mime Type. Makes it really easy for us.
String mimeType =
mDownloadManager.getMimeTypeForDownloadedFile(mDownloadedFileID);
fileIntent.setDataAndType(mostRecentDownload, mimeType);
fileIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
mContext.startActivity(fileIntent);
} catch (ActivityNotFoundException e) {
Toast.makeText(mContext, "No handler for this type of file.",
Toast.LENGTH_LONG).show();
}
// Sets up the prevention of an unintentional call. I found it necessary. Maybe not for others.
mDownloadedFileID = -1;
}
};
// Registers function to listen to the completion of the download.
mContext.registerReceiver(onComplete, new
IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
mRequest = new DownloadManager.Request(Uri.parse(url));
// Limits the download to only over WiFi. Optional.
mRequest.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);
// Makes download visible in notifications while downloading, but disappears after download completes. Optional.
mRequest.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE);
mRequest.setMimeType(mimetype);
// If necessary for a security check. I needed it, but I don't think it's mandatory.
String cookie = CookieManager.getInstance().getCookie(url);
mRequest.addRequestHeader("Cookie", cookie);
// Grabs the file name from the Content-Disposition
String filename = null;
Pattern regex = Pattern.compile("(?<=filename=\").*?(?=\")");
Matcher regexMatcher = regex.matcher(contentDisposition);
if (regexMatcher.find()) {
filename = regexMatcher.group();
}
// Sets the file path to save to, including the file name. Make sure to have the WRITE_EXTERNAL_STORAGE permission!!
mRequest.setDestinationInExternalFilesDir(mContext, Environment.DIRECTORY_DOWNLOADS, filename);
// Sets the title of the notification and how it appears to the user in the saved directory.
mRequest.setTitle(filename);
// Adds the request to the DownloadManager queue to be executed at the next available opportunity.
mDownloadedFileID = mDownloadManager.enqueue(mRequest);
}
}
_
次の行をWebViewクラスに追加して、これを既存のWebViewに追加します。
webView.setDownloadListener(new MyDownloadListener(webView.getContext()));
表示するだけでファイルを作成する必要はありません。 COLUMN_LOCAL_URIのURIは、setDataAndType()で使用できます。以下の例を参照してください。
int uriIndex = cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI);
String downloadedPackageUriString = cursor.getString(uriIndex);
Intent open = new Intent(Intent.ACTION_VIEW);
open.setDataAndType(Uri.parse(downloadedPackageUriString), mimeType);
open.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(open);