1. 程式人生 > >系統中沒有郵件客戶端設定autoLink=email會掛掉的問題

系統中沒有郵件客戶端設定autoLink=email會掛掉的問題

  TextView的autoLink屬性為我們提供了很大的便利性,當文字中有網址,郵箱或電話的時候可以讓我們方便地執行打電話發郵件等動作,不過也有一些問題,比如說設定autoLink包含email屬性,當文字中有郵件地址時只要點選就可以呼叫郵件客戶端來發郵件,但是如果當前系統中沒有郵件客戶端可供呼叫,程式會直接掛掉。

  通過看Log可以發現,系統丟擲了ActivityNotFoundException異常,並且Exception的getMessage中包含"mailto:[email protected]"字樣,當時第一反應是設定Thread.uncaughtExceptionHandler,判斷如果異常的型別是ActivityNotFoundException並且Error Message中有"mailto"字樣直接讓uncaughtException函式返回,試了一下,程式確實沒掛掉,竊喜中,但是接下來點選了一下螢幕,5秒鐘後ANR了,好吧這個方法不行。

  又想到當點選連結後會呼叫郵件客戶端發郵件,肯定有startActivity的呼叫,於是過載Activity的startActivity函式,把引數 intent的內容打出來(直接toString()就行了),發現在Intent的內容是ACTIVION_VIEW,並有extra data:mailto:[email protected],所以就通過intent包含的資訊判斷如果包含mailto字樣就認為是系統呼叫郵件客戶端發郵件,此時判斷系統中是否有郵件客戶端可處理這個請求,如果沒有就把這個startActivity事件攔截下來。

@Override
public void startActivity(Intent intent) {
    
if (intent.toString().indexOf("mailto") != -1) { // Any way to judge that this is to sead an email PackageManager pm = getPackageManager(); // The first Method List<ResolveInfo> activities = pm.queryIntentActivities(intent, 0); if (activities == null || activities.size() == 0) {
// Do anything you like, or just return return; } // Another method // ResolveInfo resolveInfo = pm.resolveActivity(intent, 0); // if (resolveInfo == null) // Yet another metod // Intent.createChooser(intent, "Choose email client"); } super.startActivity(intent); }

  程式碼就是上面這樣,很簡單,提到了三種方法,第一種和第二種都是通過PackageManager判斷是否有可以處理這個Intent的請求的元件,如果沒有就直接讓startActivity返回,在返回之前你想幹嘛幹嘛,第三種方法是通過 Intent.createChoose手動彈出一個選擇器,這個方法記得以前用是不行的,這次試了下竟然可以,難道是我記錯了?反正用前兩種方法就好了。

  不只是郵件,如果你想通過以下程式碼跳轉到應用市場讓使用者為你的應用評分

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("market://details?id=" + getPackageName()));
startActivity(intent);

  如果使用者系統中沒有安裝任何應用市場,很不幸,你的程式一樣會掛掉,和前面說的email一樣的問題:ActivityNotFoundException,不知道Google為什麼不處理一下,也許人家以為手機上怎麼可能沒有郵件客戶端和應用市場,不瞭解中國國情啊,不知道如果沒有電話應用會是什麼樣?沒有應用市場的處理是一樣的方法,過載startActivity,只要你能判斷這個請求是跳往市場的就行了。不過這個已經有了Intent物件,直接判斷就行了,判斷到沒有市場直接不startActivity。