.NET MAUI(Android)でも、データをシェア(受信)したい!
背景
データをShareしたいが、が…MAUI公式の資料には、「自分からデータを送る」というのは、書かれているが、「他アプリからデータを貰う」 という処理について、全く書かれてなかった。
ということで、実装方法を調べて、実装してみた。
基本的な資料
- MAUI公式 : アプリのライフサイクル
- Xamarin公式 : Android マニフェストの操作
- Android公式 : アクティビティの概要
- Android公式 : 他のアプリからシンプルなデータを受信する
以上、3つを読むと大体分かるかと思います。
1.マニフェストを書く
AndroidのJavaでの書き方は、こんな感じ。なのです。で、MAUIの場合も、AndroidManifest.xmlに同様に書けばいいと思ってしまいますが、実は、このプロジェクトから見えるPlatfoms/Android/AndroidManifest.xmlは、この後、この生成し直します。なので、ある意味、仮のファイルと言ってもいい感じです。そんな関係上、このAndroidManifest.xmlに書き込んでも、変な記述になってしまい、ビルド出来ません。
じゃあ、どうやって、マニフェストに適用させるかと言うと、この資料に書いてあるように、Platforms/Android/MainActivity.csを書き換えます。
このソースの様に適用したければ、
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
</intent-filter>
下記のように、書き換えることになります。
using Android.App;
using Android.Content.PM;
using Android.OS;
using Android.Content; // add ****
[Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density )]
[IntentFilter(new[] { Intent.ActionSend }, Categories = new[] { Intent.CategoryDefault }, DataMimeType = "image/*")] // Add ****
[IntentFilter(new[] { Intent.ActionSend }, Categories = new[] { Intent.CategoryDefault }, DataMimeType = "text/plain")] // Add ****
[IntentFilter(new[] { Intent.ActionSendMultiple }, Categories = new[] { Intent.CategoryDefault }, DataMimeType = "image/*")] // Add ****
public class MainActivity : MauiAppCompatActivity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
}
}
IntentFilterという記述が、AndroidManifest.xmlでは、<intent-filter> タグになります。
そんなこったで、これでビルドすると、(プロジェクトフォルダ)\obj\Debug\net6.0-android\AndroidManifest.xmlあたりに、MAUIが出力したマニフェストが出てきます。
これで、マニフェストの設定は完了です。
このマニフェストの設定が出来ると、下記の画像のように、共有リストに載るようになります。
2.アプリでデータを使用する
それでは、アプリで受信したデータを表示させましょう。
まず、Android公式では、このソースのように書くと、受信したデータを処理できるとあります。
ということで、MAUIで処理できるように書き直してみましょう。
MauiProgram.csに、下記のような感じで、書きましょう。
using Microsoft.Maui.Controls.Hosting;
using SkiaSharp.Views.Maui.Controls.Hosting;
using Microsoft.Maui.Controls.Compatibility.Hosting;
using Microsoft.Maui.LifecycleEvents;
#if ANDROID
using Android.Content;
#endif
using ****; // プロジェクト名
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.ConfigureLifecycleEvents(events =>
{
#if ANDROID
events.AddAndroid(android => android
.OnCreate((activity, bundle) => LogEvent("OnCreate", activity))
);
#endif
});
return builder.Build();
}
#if ANDROID
private static void LogEvent(string eventName, Android.App.Activity activity)
{
//System.Diagnostics.Debug.WriteLine($"Lifecycle event: {eventName}{(type == null ? string.Empty : $" ({type})")}");
Intent intent = activity.Intent;
String action = intent.Action;
String type = (String)intent.Type;
if (Intent.ActionSend.Equals(action) && type != null)
{
if ("text/plain".Equals(type))
{
handleSendText(intent); // Handle text being sent
}
else if (type.StartsWith("image/"))
{
///handleSendImage(intent); // Handle single image being sent
}
}
else if (Intent.ActionSendMultiple.Equals(action) && type != null)
{
if (type.StartsWith("image/"))
{
//handleSendMultipleImages(intent); // Handle multiple images being sent
}
}
else
{
// Handle other intents, such as being started from the home screen
}
void handleSendText(Intent intent)
{
String sharedText = intent.GetStringExtra(Intent.ExtraText);
if (sharedText != null)
{
ContactsPage.SendText = "TEST : " + sharedText;
}
}
}
#endif
}
ドンッ
これで、MAUIで、読み込むことできました。
今回は、とりあえずデータが受信できるかだけ確認したいので、テキスト文だけ受け取るという処理を書こうと思います。
今回は、実行すると、ContactsPageというContentPageで、テキスト文を表示しますので、適当にContactsPageを書いていきます。
ContactsPage.xaml.csは、下記の通り。
namespace ** プロジェクト名 **;
public partial class ContactsPage : ContentPage
{
public static event EventHandler EventSendText;
private static string _SendText{ get; set; }
public static string SendText { set {
_SendText = value;
EventSendText(null,null);
} get { return _SendText; } }
public ContactsPage()
{
InitializeComponent();
EventSendText += testEvent;
}
private void testEvent(object sender, EventArgs e){
test_message.Text = SendText;
}
}
ContactsPage.xamlは、下記の通り。
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="** プロジェクト名 **.ContactsPage"
Title="test">
<ContentPage.Content>
<ScrollView>
<StackLayout>
<Label x:Name="test_message" Text="Hello hells"></Label>
</StackLayout>
</ScrollView>
</ContentPage.Content>
</ContentPage>
ドンッ
という感じで、書きました。
解説すると、MauiProgram.csで、ContactsPage.SendTextに、受信データを代入してました。で、ContactsPageでは、ContactsPage.SendTextは、staticになってますので、代入できました。
SendTextが、書き換わったら、その情報を画面に表示してほしいので、setterから、イベントを呼び出して、動的な関数の方で、イベントを実行してもらっています。
はい。こんな感じに、テキストデータが表示出来れば、おk!
終わり!
Androidでの共有の受信処理について、書けました!
予想以上に、簡単だったね!
Discussion