Android 使用 mailto 和 tel 打开下载和 URL 时出现问题
Posted
技术标签:
【中文标题】Android 使用 mailto 和 tel 打开下载和 URL 时出现问题【英文标题】:Android problems opening downloads and urls with mailto and tel 【发布时间】:2017-06-13 04:47:50 【问题描述】:所以我遇到了一个问题,我的 webapp 在 android studio 的 webview 中运行。
我希望像 pdf 文件一样下载并在手机上的本机应用程序中打开。使用 android studio 的下载管理器可以正常工作。 我也有以“mailto:”和“tel:”开头的链接,当我不覆盖方法“shouldOverrideUrlLoading”时,这些链接会给我一个错误,我可以在其中检查它是什么类型的 url。然后打开propper inten。
因此,当我将 2 下载管理器和扩展 WebViewClient 的自定义 NavigationHandler 结合起来时,它无法按预期工作。
为了更好地了解正在发生的事情。
当我点击一个带有 pdf 文件的按钮时,它会下载该文件并显示一条 toast 消息,并使用手机上的本机应用程序打开该文件。这没有覆盖“shouldOverrideURLLoading”,也没有我扩展 WebViewClient 的类。
当我还使用自己的 NavigationHandler 女巫从 WebViewClient 扩展时, 我的带有“mailto:”和“tel:”的网址在手机上使用本机应用程序打开。 当我现在点击一个带有 pdf 文件的按钮时,它会在浏览器中打开以供下载。女巫我不要。我尝试了很多方法来解决问题,但直到现在都没有成功。
我在 WebViewClient 中运行一个网站应用程序。
附:对不起,糟糕的代码,但它对我来说是新的,还没有找到我在 Android Studio 中编码的方式。
我的 NavigationHandler 类
package nl.firejob.selector;
import android.content.Intent;
import android.net.Uri;
import android.webkit.WebView;
import android.webkit.WebViewClient;
public class NavigationHandler extends WebViewClient
private static final String TEL_PREFIX = "tel:";
private static final String MAILTO_PREFIX = "mailto:";
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
if ( url.startsWith( TEL_PREFIX ) )
// This is a tel link, which should be opened with the native thing.
Intent tel = new Intent( Intent.ACTION_DIAL, Uri.parse( url ) );
view.getContext().startActivity( tel );
return true;
else if ( url.startsWith( MAILTO_PREFIX ) )
// This is a mail link, which should be opened with the other native thing.
Intent mail = new Intent(Intent.ACTION_SENDTO);
mail.setType("message/rfc822");
mail.setData(Uri.parse( url ));
view.getContext().startActivity( mail );
return true;
else if ( Uri.parse(url).getHost().startsWith("myurl.com") )
// This is what we want to show in the app, so let the WebView handle it.
return false;
// Otherwise, the link is not for a page on my site, so launch another Activity that handles URLs
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse( url ) );
view.getContext().startActivity( intent );
return true;
我的 MainActivity 类
package nl.firejob.selector;
import android.Manifest;
import android.app.DownloadManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.webkit.DownloadListener;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.widget.Toast;
import java.io.File;
public class MainActivity extends AppCompatActivity
private WebView mWebView;
private DownloadManager dm;
private Long myDownloadReference;
private BroadcastReceiver receiveDownloadComplete;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mWebView = (WebView) findViewById(R.id.webView);
// Allow webview to use javascript
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
// Stop local links/redirects from opening in browser instead of WebView
mWebView.setWebViewClient(new NavigationHandler()
@Override
public void onPageFinished(WebView view, String url)
// Show the webview
findViewById(R.id.webView).setVisibility(View.VISIBLE);
// Hide splashscreen objects
findViewById(R.id.imageLogo).setVisibility(View.GONE);
findViewById(R.id.textLogo).setVisibility(View.GONE);
);
mWebView.setDownloadListener(new DownloadListener()
@Override
public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength)
if( haveStoragePermission())
Log.i("download url",url);
//for downloading directly through download manager
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
request.allowScanningByMediaScanner();
request.setVisibleInDownloadsUi(true);
request.setDescription("Doorvoerboek").setTitle("doorvoerboek.pdf");
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "doorvoerboek.pdf");
dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
myDownloadReference = dm.enqueue(request);
IntentFilter intentFilter = new IntentFilter( dm.ACTION_DOWNLOAD_COMPLETE);
receiveDownloadComplete = new BroadcastReceiver()
@Override
public void onReceive(Context context, Intent intent)
long reference = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
if (myDownloadReference == reference)
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(reference);
Cursor cursor = dm.query(query);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(DownloadManager.COLUMN_STATUS);
int status = cursor.getInt(columnIndex);
int fileNameIndex = cursor.getColumnIndex(DownloadManager.COLUMN_TITLE);
String saveFilePath = cursor.getString(fileNameIndex);
Log.i("filename",saveFilePath);
int columnReason = cursor.getColumnIndex(DownloadManager.COLUMN_REASON);
int reason = cursor.getInt(columnReason);
switch (status)
case DownloadManager.STATUS_SUCCESSFUL:
Toast.makeText(MainActivity.this, "Download Complete", Toast.LENGTH_LONG).show();
Log.i("dir", Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath() );
File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath() +"/doorvoerboek.pdf");
Intent intentView = new Intent(Intent.ACTION_VIEW);
intentView.setDataAndType(Uri.fromFile(file),"application/pdf");
intentView.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(intentView);
break;
;
registerReceiver(receiveDownloadComplete,intentFilter);
);
mWebView.loadUrl("http://myurl.com/");
public boolean haveStoragePermission()
if (Build.VERSION.SDK_INT >= 23)
if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED)
Log.e("Permission error","You have permission");
return true;
else
Log.e("Permission error","You have asked for permission");
ActivityCompat.requestPermissions(this, new String[]Manifest.permission.WRITE_EXTERNAL_STORAGE, 1);
return false;
else //you dont need to worry about these stuff below api level 23
Log.e("Permission error","You already have the permission");
return true;
@Override
public boolean onKeyDown(int keyCode, KeyEvent event)
if ((keyCode == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack())
//if Back key pressed and webview can navigate to previous page
mWebView.goBack();
// go back to previous page
return true;
else
finish();
// finish the activity
return super.onKeyDown(keyCode, event);
【问题讨论】:
【参考方案1】:此代码下载任何文件。
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webview = (WebView) findViewById(R.id.webView);
spinner = (ProgressBar) findViewById(R.id.progressBar1);
webview.setWebViewClient(new CustomWebViewClient());
webview.getSettings().setUseWideViewPort(true);
webview.getSettings().setLoadWithOverviewMode(true);
webview.getSettings().setBuiltInZoomControls(true);
webview.getSettings().setDisplayZoomControls(false);
webview.getSettings().setJavaScriptEnabled(true);
webview.getSettings().setDomStorageEnabled(true);
webview.setOverScrollMode(WebView.OVER_SCROLL_NEVER);
webview.loadUrl("http://www.website.com");
//Download file code ***.com
webview.setDownloadListener(new DownloadListener()
@Override
public void onDownloadStart(String url, String userAgent,
String contentDisposition, String mimetype,
long contentLength)
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
DownloadManager dm = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
dm.enqueue(request);
Toast.makeText(getApplicationContext(), "downloading",
Toast.LENGTH_LONG).show();
);
// Download section of code
// Close of onCreate
// mailto code ***.com
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
if( url.startsWith("http:") || url.startsWith("https:") )
return false;
// Otherwise allow the OS to handle it
else if (url.startsWith("tel:"))
Intent tel = new Intent(Intent.ACTION_DIAL, Uri.parse(url));
startActivity(tel);
return true;
else if (url.startsWith("mailto:"))
String body = "Enter your Question, Enquiry or Feedback below:\n\n";
Intent mail = new Intent(Intent.ACTION_SEND);
Intent intent = mail.setType("application/octet-stream");
MailTo recipient = MailTo.parse(url);
mail.putExtra(Intent.EXTRA_EMAIL, new String[]recipient.getTo());
mail.putExtra(Intent.EXTRA_SUBJECT, "Contact");
mail.putExtra(Intent.EXTRA_TEXT, body);
startActivity(mail);
return true;
return true;
// mailto section of code
【讨论】:
以上是关于Android 使用 mailto 和 tel 打开下载和 URL 时出现问题的主要内容,如果未能解决你的问题,请参考以下文章
如何在 WebView Flutter 中允许 mailto 和 tel URL 方案?
Skype 是不是有 href 属性,例如“mailto:”或“tel:”?