Xamarin.Android インテント
1 インテント
インテントには、暗黙的インテントと明示的インテントがあります。
(1) 明示的インテント
アクティビティ名を具体的に指定する。先のActivity起動が、そのものズバリです。
StartActivity(new Intent(this,typeof (Activity2)));
(2) 暗黙的インテント
データとアクションを指定して、システムがアクティビティを選択するのも。
//var intent = new Intent(Intent.ActionView, Android.Net.Uri.Parse("http://www.google.com")); var intent = new Intent(Intent.ActionView); intent.SetData(Android.Net.Uri.Parse("http://www.google.com")); StartActivity(intent);
下記のコードで、デフォルトでインストールされているブラウザが起動する。
//アクション : ACTION_VIEW //データ : URL var intent = new Intent(Intent.ActionView); intent.SetData(Android.Net.Uri.Parse("http://www.google.com")); StartActivity(intent); //暗黙的インテントによるActivity起動
2 マニュフェストの編集
システムが暗黙的にインテントを選択するとき、インテントフィルタが使用される。AndroidManifest.xmlに
(1) AndroidManifest.xmlの自動生成
Xamarin Developer CenterのGuidesには、Xamarinでは、AndroidManifest.xmlを手動でいじることは99%ないと書かれていました。
http://docs.xamarin.com/guides/android/advanced_topics/working_with_androidmanifest.xml/
属性を指定することで、AndroidManifest.xmlに自動追加させる事が推奨されているようです。
ソリューションエクスプローラで見えているAndroidManifest.xmlは、自動追加前の状態で、コンパイル後に自動追加されたものが、ソリューション\\obj\\Debug\\androidの下に生成されています。
ソリューションエクスプローラで見えているもの
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"> <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="8" /> <application></application> <my>試験的に手動で追加</my> </manifest>
自動生成されたもの
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="AndroidApplication1.AndroidApplication1"> <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="8" /> <application android:name="mono.android.app.Application" android:debuggable="true"> <activity android:icon="@drawable/icon" android:label="AndroidApplication1" android:name="androidapplication1.Activity1"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <provider android:name="mono.MonoRuntimeProvider" android:exported="false" android:initOrder="2147483647" android:authorities="AndroidApplication1.AndroidApplication1.mono.MonoRuntimeProvider.__mono_init__" /> <receiver android:name="mono.android.Seppuku"> <intent-filter> <action android:name="mono.android.intent.action.SEPPUKU" /> <category android:name="mono.android.intent.category.SEPPUKU.AndroidApplication1.AndroidApplication1" /> </intent-filter> </receiver> </application> <my>試験的に手動で追加</my> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> </manifest>
(2) inten-filterの追加
属性指定でinten-filterを追加するコードは下記のようになります。
[Activity(Label = "MyApp")] [IntentFilter(new[] { Intent.ActionView }, Categories = new[] { Intent.CategoryDefault },DataScheme = "http")]
この時、自動生成されたAndroidManifest.xmlには、ちゃんとinten-filter追加されていた。
<activity android:label="MyApp" android:name="test1.HTTPActivty"> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <data android:scheme="http" /> </intent-filter> </activity>
3 インテント解決(1) スキーム追加
新しいActivity(Activity2)を追加し、先の要領でプロトコルhttpにインテントフィルタを追加すると、暗黙的インテントで、httpを呼び出したとき、選択ダイアログが表示されるようになります。
[Activity(Label = "MyApp")] [IntentFilter(new[] { Intent.ActionView }, Categories = new[] { Intent.CategoryDefault }, DataScheme = "http")] public class Activity2 : Activity{
(2) ホストやポート番号の追加
スキーム以外にも、ホストやポート番号なども指定可能です。スキームだけでなくホスト、ポート番号を指定する要領は、次のようになります。
[Activity(Label = "MyApp")] [IntentFilter(new[] { Intent.ActionView }, Categories = new[] { Intent.CategoryDefault }, DataScheme = "http", DataHost = "sample.com", DataPort = "1234")] public class Activity2 : Activity{
この時生成されたマニフェストは下記の通り。
<activity android:label="MyApp" android:name="androidapplication1.Activity2"> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <data android:host="sample.com" android:port="1234" android:scheme="http" /> </intent-filter> </activity>
上記のフィルタを登録した状態では、「http://sample.com:1234」を指定した場合だけ、選択ダイアログが表示され、それ以外のhttpでは、ダイレクトにブラウザが起動します。
なお、Activity2は、同一アプリ内に存在する必要はありません。別のアプリにあるActivityでも動作は同じです。
ちなみに、登録されるのに少し時間がかかるのか・・・?
呼び出されるActivitiyを再コンパイルすると、利用できるようになるまでに数十秒かかる事がありました。
Xamarin.Android 暗黙的インテントで「共有」に追加してみる
1 インテントフィルタの登録ブラウザのメニューに「共有」というのがあり、各種アプリにURLやタイトルを送れるようになっています。今回は、この共有メニューに自作のアプリを追加してみます。
「共有」に表示されるようにするには、categoryに「category.DEFAULT」、mimeTypeに「text/plain」、actionに「action.SEND」をそれぞれ登録しておく必要があります。
属性を使用して上記の3つをセットしたものは、下記の通りになります。
[Activity(Label = "MyApp")] [IntentFilter(new[]{Intent.ActionSend}, Categories = new[]{Intent.CategoryDefault},DataMimeType = "text/plain")] public class Activity2 : Activity{
登録が完了すると、ブラウザメニューの「共有」に、自作アプリが列挙されるようになります。
2 インテントからのデータ取得起動されたアプリ側で、起動元から送られたデータを取得するには、Intent.Extrasを使用します。
Intent.Extrasからデータを取り出すには、キー文字列が必要ですが、このキーは、Intent.Extras.KeySet()で列挙できます。下記のコードは、取得したデータを一覧したものです。
なお、起動時にIntent.Actionを確認することで、このアプリが起動された方法を確認することができます。
[Activity(Label = "MyApp")] [IntentFilter(new[]{Intent.ActionSend}, Categories = new[]{Intent.CategoryDefault},DataMimeType = "text/plain")] public class Activity2 : Activity{ protected override void OnCreate(Bundle bundle){ base.OnCreate(bundle); //このActivityが起動された方法を確認する if (Intent.Action==Intent.ActionSend) { var sb = new StringBuilder(); //呼び出し元からのデータを受け取る foreach (var key in Intent.Extras.KeySet()){//キーの一覧 var value = Intent.Extras.Get(key); sb.Append(string.Format("■key:{0}\r\n valse:{1}\r\n", key, value)); } Toast.MakeText(this,sb.ToString(),ToastLength.Short).Show(); } } }
キーには、次のようなものが見てとれます。
android.Intent.extra.TEXT : URL
android.Intent.extra.SUBJECT : タイトル
share_favicon
share_screenshot