如何進入系統撥號盤,或者直接打電話,發簡訊,還有data,scheme,uri的關係
一.背景
Android做app,有時候需要去呼叫系統的撥號盤,或者直接撥打某個電話,還有傳送簡訊(直接傳送和帶著預設的號碼和內容跳到系統應用),網上有很多例子,可以直接拿來用,可是如果換做是呼叫其他的系統應用你會咩?
下面就授之以漁!!!
二.例項
用一個跳到簡訊的需求來講怎麼查原始碼(點我獲取應用層程式碼)。
(1)首先用模擬器開啟新建簡訊,觀察開啟了什麼Activity
(2)從上面可以發現啟動了ComposeMessageActivity,接下來檢視他的原始碼和Intent-filter
(3)檢視
通過上面就可以知道怎麼跳到資訊應用,很多會對 Data,MineType還有Scheme搞不清,等會我就區分下,先講完這裡,如果要帶著內容怎麼搞?
(4)看看怎麼帶著內容跳到系統的資訊應用
所以綜上基本就可以知道怎麼用了
(5)程式碼
詳細的原始碼就不放了,不能再簡單了。。。public class MainActivity extends AppCompatActivity implements View.OnClickListener { private Button btDialDirect; private Button btDialInDirect; private Button btSendSms; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btDialDirect = (Button) findViewById(R.id.bt_dial_direct); btDialInDirect = (Button) findViewById(R.id.bt_dial_indirect); btSendSms = (Button) findViewById(R.id.bt_sendSms); btSendSms.setOnClickListener(this); btDialDirect.setOnClickListener(this); btDialInDirect.setOnClickListener(this); } @Override public void onClick(View v) { Intent intent = new Intent(); Uri data = null; if(btDialDirect == v){ //直接打出去 intent.setAction(Intent.ACTION_CALL); data = Uri.parse("tel:"+110); }else if(btDialInDirect == v){ //跳到撥號盤然後自己打 intent.setAction(Intent.ACTION_DIAL); data = Uri.parse("tel:"+110); }else if(btSendSms == v){ intent.setAction(Intent.ACTION_SENDTO); data = Uri.parse("smsto:" + 5556); intent.putExtra("sms_body","come here"); } intent.setData(data); startActivity(intent); } }
三.講講data,scheme,uri的關係
Activity之間的跳轉分為2種:
(1)顯式跳轉:
在可以引用到那個類, 並且可以引用到那個類的位元組碼時可以使用。一般用於自己程式的內部。顯式跳轉不可以跳轉到其他程式的頁面中。
(2) 隱式跳轉:
可以在當前程式跳轉到另一個程式的頁面。隱式跳轉不需要引用到那個類,但是必須得知道那個介面的動作(action)和資訊(category),有時還需要Data。
Activity之間通過Intent進行通訊。Intent即意圖,用於描述一個頁面的資訊,同時也是一個數據的載體。
隱式跳轉的Activity(自己寫這個Activity要在清單檔案註冊action,和category,data(有時),
因為自己的如果不註冊,那觸發這些action,category都不知道是啟動哪個Activity隱式跳轉可以跳轉到其他程式的Activity,只要知道Activity的動作(action)以及資訊(category)。因此,能夠被隱式跳轉的Activity,在清單檔案中宣告時必須指定動作和資訊這兩個屬性。
上面的寫的android.intent.category.DEFAULT可以不寫,原因是系統用過startActivity或者startActivityForResult的時候會預設為Intent加上“android.intent.category.Default”這個category
(3)系統入口:
若清單檔案中的Activity宣告為:
則此Activity將作為程式的入口,有幾個作為入口的Activity,apk檔案安裝的時候就會生成幾個圖示。
(4)data,mimeType和URI的區別
<data android:scheme="http" />
<data android:scheme="https" />
<data android:scheme="inline" />
<data android:mimeType="text/html"/>
<data android:mimeType="text/plain"/>
<data android:mimeType="application/xhtml+xml"/>
<data android:mimeType="application/vnd.wap.xhtml+xml"/>
或者
<data android:scheme="http"
android:scheme="https"
android:scheme="inline"
android:mimeType="text/html"
android:mimeType="text/plain"
android:mimeType="application/xhtml+xml"
android:mimeType="application/vnd.wap.xhtml+xml"/>
可以看出上面的data由兩部分組成,mimeType和URI組成
mimeType(媒體型別,比如 image/jpeg,audio/mpeg4-generic 和video)
URI,下面是它的結構<scheme>://<host>:<port>/[<path>|<pathPrefix>|<pathPattern>]
實際例子
Content://com.example.project:200/folder/subfolder/etc
Scheme:URI的模式(URI預設值為content和file),比如http,file,content等,如果URI中沒有指定scheme,那麼整個URI的其他引數無效,他也意味著URI是無效的(就像Uri.parse("smsto:" + 5556);如果沒有寫smsto,那後面的5556就沒有什麼軟用)
Host:是URI的主機名
Port:URI中的埠號
注意:
<intent-filter> <data android:mimeType="image/*" />。。。</intent-filter>
意這種規則制定了媒體型別為所有型別的圖片,雖然沒有指定URI,但是卻有預設值,(URI預設值為content和file),也就是雖然沒有指定URI,但是Intent中的URI部分的scheme必須為Content或者file才能匹配
intent.setDataAndType(Uri.parse(“file://abc”),”image/png”).(注意setData和setType不能單獨寫否則會互相清空)
(5)一些注意事項
Intent-Filter的匹配規則對於Service和BroadCastReceiver也是同樣的道理,不過系統對於service的建議是儘量使用顯示呼叫方式來啟動服務。
但是要注意一點,如果硬是方式開啟一個Activity的時候,需要做一個判斷,看是否有Activity能夠匹配我們的隱式Intent
判斷是否有匹配的隱式 (避免不匹配直接崩掉)
1.PackManager resolveActivity
2.Intent resolveActivity
3.PackMagager querryIntentActivityes,這個方法和resolveActivity方法不同的是:它不是返回最佳匹配的Activity資訊而是返回所有成功匹配的Activity資訊,我們看一下兩者的原型
Public abstract List<ResolveInfo> queryIntentActivities(Intent intent, int flags)
Public abstract ResolveInfo resolveActivity (Intent intent ,int flags)
第二個引數要使用 MATCH_DEFAULT_ONLY 這個標記位,這個標記為的含義是僅僅匹配那些在intent-filter中聲明瞭<category android:name = “android.intent.category.Default/>”這個category的Activity
這個標記為的意義在於,只要上述的兩個方法不返回null,那麼startActivity一定可以成功,如果不用這個標記位,就會把intent-filter中category不含Default的那些Activity匹配出來,從而導致導致startActivity可能失敗,因為不含有Default這個category的Activity是無法接收隱式Intent