Webビューでダウンロードをサポート
13913 ワード
最近、開発の過程で、WebViewがapkのダウンロードなどのファイルのダウンロードをサポートする必要があります.WebViewのデフォルトではダウンロードはサポートされていません.開発者が自分で実現する必要があります.PMが需要を提出した以上、私たちは袖を引っ張ってやりましょう.そこで、ネット上でいくつかの方法を探しました.主な考え方はこのようにいくつかあります.ジャンプブラウザダウンロード 使用システムのダウンロードサービス カスタムダウンロードタスク 考えがあればやりやすいので、具体的な実現を紹介します.WebViewがダウンロードをサポートするには、WebViewにダウンロードリスナー
1.ブラウザからのダウンロード
この方法は最も簡単で乱暴で、直接ダウンロードの任務をブラウザに投げて、残りは私たちが管理する必要はありません.欠点はダウンロード完了を感知できないことであり、apkのダウンロード完了後にインストールインタフェースを開くなどの後続の処理は当然ない.
2.システムを利用したダウンロードサービス
DownloadManagerはシステムが提供するダウンロード処理のためのサービスで、利用者はダウンロードURIとストレージパスを提供し、簡単な設定を行うだけです.DownloadManagerはバックグラウンドでダウンロードを行い、ダウンロードに失敗した場合、ネットワークの切り替え、システムの再起動後に再ダウンロードを試みます.
これでダウンロードタスクを追加し、システムのダウンロードが完了するのを静かに待ちましょう.また、読み取りと書き込みの外部ストレージ権限とネットワーク権限を追加することを忘れないでください.では、ファイルのダウンロードに成功したことをどのように知っていますか.ダウンロードが完了すると、タスクIDが入ったブロードキャストが送信され、呼び出し元にタスクが完了したことを伝え、DownloadManagerでファイル情報を取得すればさらに処理できます.
Ok、ここまで、システムサービスを利用してダウンロードが終わっても、簡単にまとめます.私たちは開始と完了だけに関心を持っています.ダウンロード中の一時停止、再試行などのメカニズムについては、システムが私たちを助けてくれました.とても友好的ではありませんか.
3.カスタムダウンロードタスク
ダウンロードリンクがあれば、自分でネットワーク部分を実現することができます.私はここでダウンロードタスクをカスタマイズしました.HttpURLConnectionとAsyncTaskを使って実現しましたが、コードは簡単です.
利点は、ダウンロードの進捗状況を感知し、開始、キャンセル、失敗、完了などのイベントを処理することであり、不足点はダウンロードの制御がシステムサービスに及ばず、自分でネットワークによる問題を処理しなければならないことである.
setDownloadListener
を設定する必要があります.DownloadListenerにはonDownloadStartという方法しかありません.ファイルがダウンロードする必要があるたびに、この方法はコールバックされ、ダウンロードしたURLはメソッドパラメータを通じて伝達され、ダウンロードイベントをここで処理することができます.mWebView.setDownloadListener(new DownloadListener() {
@Override
public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimeType, long contentLength) {
// TODO: 2017-5-6
}
});
1.ブラウザからのダウンロード
この方法は最も簡単で乱暴で、直接ダウンロードの任務をブラウザに投げて、残りは私たちが管理する必要はありません.欠点はダウンロード完了を感知できないことであり、apkのダウンロード完了後にインストールインタフェースを開くなどの後続の処理は当然ない.
private void downloadByBrowser(String url) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.addCategory(Intent.CATEGORY_BROWSABLE);
intent.setData(Uri.parse(url));
startActivity(intent);
}
2.システムを利用したダウンロードサービス
DownloadManagerはシステムが提供するダウンロード処理のためのサービスで、利用者はダウンロードURIとストレージパスを提供し、簡単な設定を行うだけです.DownloadManagerはバックグラウンドでダウンロードを行い、ダウンロードに失敗した場合、ネットワークの切り替え、システムの再起動後に再ダウンロードを試みます.
private void downloadBySystem(String url, String contentDisposition, String mimeType) {
//
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
// , 、
request.allowScanningByMediaScanner();
// ,
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
// , ,
// request.setTitle("This is title");
//
// request.setDescription("This is description");
//
request.setAllowedOverMetered(false);
//
request.setVisibleInDownloadsUi(false);
//
request.setAllowedOverRoaming(true);
//
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);
//
String fileName = URLUtil.guessFileName(url, contentDisposition, mimeType);
log.debug("fileName:{}", fileName);
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName);
// ,
// request.setDestinationUri()
// request.setDestinationInExternalFilesDir()
final DownloadManager downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
//
long downloadId = downloadManager.enqueue(request);
log.debug("downloadId:{}", downloadId);
}
これでダウンロードタスクを追加し、システムのダウンロードが完了するのを静かに待ちましょう.また、読み取りと書き込みの外部ストレージ権限とネットワーク権限を追加することを忘れないでください.では、ファイルのダウンロードに成功したことをどのように知っていますか.ダウンロードが完了すると、タスクIDが入ったブロードキャストが送信され、呼び出し元にタスクが完了したことを伝え、DownloadManagerでファイル情報を取得すればさらに処理できます.
private class DownloadCompleteReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
log.verbose("onReceive. intent:{}", intent != null ? intent.toUri(0) : null);
if (intent != null) {
if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(intent.getAction())) {
long downloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
log.debug("downloadId:{}", downloadId);
DownloadManager downloadManager = (DownloadManager) context.getSystemService(DOWNLOAD_SERVICE);
String type = downloadManager.getMimeTypeForDownloadedFile(downloadId);
log.debug("getMimeTypeForDownloadedFile:{}", type);
if (TextUtils.isEmpty(type)) {
type = "*/*";
}
Uri uri = downloadManager.getUriForDownloadedFile(downloadId);
log.debug("UriForDownloadedFile:{}", uri);
if (uri != null) {
Intent handlerIntent = new Intent(Intent.ACTION_VIEW);
handlerIntent.setDataAndType(uri, type);
context.startActivity(handlerIntent);
}
}
}
}
}
//
DownloadCompleteReceiver receiver = new DownloadCompleteReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
registerReceiver(receiver, intentFilter);
Ok、ここまで、システムサービスを利用してダウンロードが終わっても、簡単にまとめます.私たちは開始と完了だけに関心を持っています.ダウンロード中の一時停止、再試行などのメカニズムについては、システムが私たちを助けてくれました.とても友好的ではありませんか.
3.カスタムダウンロードタスク
ダウンロードリンクがあれば、自分でネットワーク部分を実現することができます.私はここでダウンロードタスクをカスタマイズしました.HttpURLConnectionとAsyncTaskを使って実現しましたが、コードは簡単です.
private class DownloadTask extends AsyncTask<String, Void, Void> {
// :URL
private String url;
private String destPath;
@Override
protected void onPreExecute() {
log.info(" ");
}
@Override
protected Void doInBackground(String... params) {
log.debug("doInBackground. url:{}, dest:{}", params[0], params[1]);
url = params[0];
destPath = params[1];
OutputStream out = null;
HttpURLConnection urlConnection = null;
try {
URL url = new URL(params[0]);
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setConnectTimeout(15000);
urlConnection.setReadTimeout(15000);
InputStream in = urlConnection.getInputStream();
out = new FileOutputStream(params[1]);
byte[] buffer = new byte[10 * 1024];
int len;
while ((len = in.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
in.close();
} catch (IOException e) {
log.warn(e);
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (out != null) {
try {
out.close();
} catch (IOException e) {
log.warn(e);
}
}
}
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
log.info(" ");
Intent handlerIntent = new Intent(Intent.ACTION_VIEW);
String mimeType = getMIMEType(url);
Uri uri = Uri.fromFile(new File(destPath));
log.debug("mimiType:{}, uri:{}", mimeType, uri);
handlerIntent.setDataAndType(uri, mimeType);
startActivity(handlerIntent);
}
}
private String getMIMEType(String url) {
String type = null;
String extension = MimeTypeMap.getFileExtensionFromUrl(url);
log.debug("extension:{}", extension);
if (extension != null) {
type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
}
return type;
}
//
mWebView.setDownloadListener(new DownloadListener() {
@Override
public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimeType, long contentLength) {
String fileName = URLUtil.guessFileName(url, contentDisposition, mimeType);
String destPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
.getAbsolutePath() + File.separator + fileName;
new DownloadTask().execute(url, destPath);
}
});
利点は、ダウンロードの進捗状況を感知し、開始、キャンセル、失敗、完了などのイベントを処理することであり、不足点はダウンロードの制御がシステムサービスに及ばず、自分でネットワークによる問題を処理しなければならないことである.