文档结构  
翻译进度:已翻译     翻译赏金:0 元 (?)    ¥ 我要打赏

我最喜欢的Android的部分是它的通知系统,它使开发者可以从主程序之外直接与用户联系. 随着Android N的推出, Android N的通知栏正在使用一种全新的Material Design风格改造视觉效果,这种风格的修改内容包括重新排列布局、修改内容大小用来,而他们达到的效果会使通知内容更好的显示细节(如app名和消息排列方式)以及更好的理解. 下面是一张Android M到N的视觉变化概览图:

Android N并不仅仅升级了视觉效果, 也提供了一打使开发者收益的强大的新功能. 捆绑通知 功能让开发者可以使用Builder.SetGroup()方法为通知分组. Custom Views 已增强的自定义视图功能,现在可以使用系统通知标题,actions,并且可以使用自定义视图扩展布局. 但是, 我嘴喜欢的新特性是直接回复, 它让用户可以直接在通知里回复,而不是非要打开应用到应用里回复. 这跟Android Wear应用的可以直接发信息给主程序的功能是相似的。

第 1 段(可获 2.44 积分)

开始

在以前版本的Android系统中, 开发者们能够通过处理通知的点击事件发送action, 使用action的时候这么做(点击通知操作)会启动一个Activity或者一个服务/广播接收器. 直接回复这个想法是通过扩展一个action操作,为其加入远程输入功能,使用户可以直接回复而不必启动整个应用. 在老版本的系统中处理回复通知最好的方法是在Activity内部,但是现在用户可以直接回复通知了.

实现直接回复功能的前提是,我们必须有一个可以接收和处理来自用户的回复信息的操作的广播接收器或者服务对象. 例如,我们将从MainActivity启动一个通知,这个通知会发送一个值为“com.xamarin.directreply.REPLY”的Intent对象,这样我们的广播接收器就能把它过滤出来。.

第 2 段(可获 1.86 积分)

首先,确保已经安装了最新的 Android Support Library v4 NuGet 库用以兼容通知功能。

在 MainActivity 中, 建立以下几个常量:

int requestCode = 0;
 
public const string REPLY_ACTION = "com.xamarin.directreply.REPLY";
public const string KEY_TEXT_REPLY = "key_text_reply";
public const string REQUEST_CODE = "request_code";

创建Pending Intent对象

Pending Intent对象是一个描述了目标 action 操作并与之执行的Intent对象.这种情况下,如果用户使用Android N,我们会创建一个能够触发回复动作的Pending Intent对象,或者如果用户使用低版本的Android,Pending Intent会启动Main Activity.

Intent intent = null;
PendingIntent pendingIntent= null;
//If Android N then enable direct reply, else launch main activity.
if ((int)Build.VERSION.SdkInt >= 24)
{
    intent = new Intent(REPLY_ACTION)
			.AddFlags(ActivityFlags.IncludeStoppedPackages)
			.SetAction(REPLY_ACTION)
			.PutExtra(REQUEST_CODE, requestCode);
 
    pendingIntent = PendingIntent.GetBroadcast(this, requestCode, intent, PendingIntentFlags.UpdateCurrent);
}
else
{
    intent = new Intent(this, typeof(MainActivity));
    intent.AddFlags(ActivityFlags.ClearTop | ActivityFlags.NewTask);
 
    pendingIntent = PendingIntent.GetActivity(this, requestCode, intent, PendingIntentFlags.UpdateCurrent);
}
第 3 段(可获 1.23 积分)

建立并附加用户远程输入内容

直接回复功能的关键点是创建和附加用户的远程输入内容,这将会通知Android当前的操作是一个直接回复动作,并且这样的话就可以允许用户输入内容.

var replyText = "Reply to message...";
 
//create remote input that will read text
var remoteInput = new Android.Support.V4.App.RemoteInput.Builder(KEY_TEXT_REPLY)
						        .SetLabel(replyText)
                                                        .Build();

当我们得到用户的远程输入后,我们可以创建一个新的action并把它附加进去:

第 4 段(可获 0.74 积分)
var action = new NotificationCompat.Action.Builder(Resource.Drawable.action_reply,
                                                   replyText,
                                                   pendingIntent)											          
                                                  .AddRemoteInput(remoteInput)
                                                  .Build();

构建和发送通知

我们已经创建完了带有远程输入功能的action对象,最后让我们来发送通知.

var notification = new NotificationCompat.Builder(this)
					 .SetSmallIcon(Resource.Drawable.reply)
					 .SetLargeIcon(BitmapFactory.DecodeResource(Resources, Resource.Drawable.avatar))
					 .SetContentText("Hey, it is James! What's up?")
					 .SetContentTitle("Message")
					 .SetAutoCancel(true)
                                         .AddAction(action)
					 .Build();
 
using (var notificationManager = NotificationManagerCompat.From(this))
{
	notificationManager.Notify(requestCode, notification);
}
第 5 段(可获 0.24 积分)

现在我们的通知内容是与远程输入就可以显示出来:

处理输入内容

当用户在直接回复功能里输入文本,我们就可以通过下面的代码从Intent对象里取回信息:

var remoteInput = RemoteInput.GetResultsFromIntent(Intent);
var reply = remoteInput?.GetCharSequence(MainActivity.KEY_TEXT_REPLY) ?? string.Empty;

这些操作应该放在后台服务或者广播接收器对象里,并且指定Intent过滤内容:“com.xamarin.directreply.REPLY” .

这是最终的BroadcastReceiver对象,它会弹出一条信息,并且会停止通知中的进度条:

[BroadcastReceiver(Enabled = true)]
[Android.App.IntentFilter(new[] { MainActivity.REPLY_ACTION })]
/// <summary>
/// A receiver that gets called when a reply is sent
/// </summary>
public class MessageReplyReceiver : BroadcastReceiver
{
	public override void OnReceive(Context context, Intent intent)
	{
		if (!MainActivity.REPLY_ACTION.Equals(intent.Action))
			return;
		
 
		int requestId = intent.GetIntExtra(MainActivity.REQUEST_CODE, -1);
		if (requestId == -1)
			return;
 
		var reply = GetMessageText(intent);
		using (var notificationManager = NotificationManagerCompat.From(context))
		{
			//Create new notification to display, or re-build existing conversation to update with new response
			var notificationBuilder = new NotificationCompat.Builder(context);
			notificationBuilder.SetSmallIcon(Resource.Drawable.reply);
			notificationBuilder.SetContentText("Replied");
			var repliedNotification = notificationBuilder.Build();
 
 
			//Call notify to stop progress spinner. 
			notificationManager.Notify(requestId, repliedNotification);
		}
 
		Toast.MakeText(context, $"Message sent: {reply}", ToastLength.Long).Show();
	}
 
	/// <summary>
	/// Get the message text from the intent.
	/// Note that you should call <see cref="Android.Support.V4.App.RemoteInput.GetResultsFromIntent(intent)"/> 
	/// to process the RemoteInput.
	/// </summary>
	/// <returns>The message text.</returns>
	/// <param name="intent">Intent.</param>
	static string GetMessageText(Intent intent)
	{
		var remoteInput = RemoteInput.GetResultsFromIntent(intent);
		return remoteInput?.GetCharSequence(MainActivity.KEY_TEXT_REPLY) ?? string.Empty;
	}
}
第 6 段(可获 1.09 积分)

了解更多

要了解Android N中更强大的功能, 包括增加的通知功能, 请阅读文档 Android N Getting Started Guide. 这里你可以找到一个完整的直接回复的示例和其他增强的通知功能 Samples Gallery.

第 7 段(可获 0.53 积分)

文章评论

访客
为什么右边出现了c#代码