🎃

.NET MAUI(Android)でも、データをシェア(受信)したい!

2022/07/14に公開

背景

データをShareしたいが、が…MAUI公式の資料には、「自分からデータを送る」というのは、書かれているが、「他アプリからデータを貰う」 という処理について、全く書かれてなかった。

ということで、実装方法を調べて、実装してみた。

基本的な資料

以上、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