本篇主要介绍Android N系统改动中的多窗口模式跟消息推送的特性与修改。写在这里一是帮助自己理解,二是分享给有需要的开发者们

一、支持多窗口模式(Multi-window support)


多窗口模式顾名思义就是在界面上同事显示两个界面的应用界面。这种模式使用场景常用于你在看视频,或者玩游戏 这时候弹出了一个消息需要查看和回复。

多窗口模式分为以下模式:

           Side-By-Side 模式:两个 App 瓜分一个屏幕
           One-above-the-other 模式:一个 App 浮动在另一个 App 之上

Android Tv上还有一种picture In picture模式。

分屏时应用会有一条分界面,用户可以拖动分界线来让其中一个应用占据更多的屏幕,另外那个看起来就要小一点。

进入多窗口模式有如下两种方法:




android 多 android多窗口模式_Android N 新特性

开发者们需要注意以下几点:



      2.当用户把你的应用拖入多窗口模式的时候,你的一些配置、布局属性等都会发生改变,甚至重建,如: 从竖屏切换到横屏等。要妥善处理这些重建行为,Activity 必须通过常规的Activity 生命周期恢复其以前的状态,在 Activity 生命周期中,Android 会在销毁 Activity 之前调用 onSaveInstanceState(),以便您保存有关应用状态的数据。 然后,您可以在 onCreate() 或 onRestoreInstanceState() 期间恢复 Activity 状态。更多具体的变化可以参考 Handling Runtime Changes


android:resizeableActivity=["true" | "false"]

来确定你的应用是否支持多窗口模式。(TargetSDK为Android N时,即使不设置,该属性默认开启)

resizeableActivity需要配置在<Application>或者<Activity>里。如果把这个属性配置在某个根Activity上,那么他所有的任务堆栈里的Activity都拥有该属性。

targetSDK低于Android N的应用运行在Android N设备上时,如果应用是多方向的(可横屏可竖屏),当用户尝试在多窗口模式操作这个应用时,将会被弹窗警告,并且系统会强制重新调整界面;而如果是固定方向的应用,如果用户试图将其拖入多窗口模式,应用不会被重新调整,但是会直接全屏显示。

     4. Android N还在Manifest的Layout 中添加了4个属性:

android:defaultWidth    Activity在自由模式下启动的默认宽度

android:defaultHeight   Activity在自由模式下启动的默认高度


android:gravity        Activity在自由模式下启动的初始化位置

android:minimalSize     Activity在自由模式和多窗口模式下的最小宽高  (这里需要注意:用户如果拖动分界线将你的应用减小,那么系统将以用户拖动后的宽高为准,该参数此时不起作用)

      代码示例:

<activity android:name=".MyActivity">
    <layout android:defaultHeight="500dp"
          android:defaultWidth="600dp"
          android:gravity="top|end"
          android:minimalSize="450dp" />
</activity>


Activity中新增以下方法:

Activity.inMultiWindow()  查询Activity是否处于多窗口模式

Activity.inPictureInPicture()  查询Activity是否处于picture-in-picture模式(Android Tv多窗口模式中的一种特定模式,该方法返回true的时候,Activity.inMultiWindow()肯定返回true)

Activity.onMultiWindowChanged()  Activity进入/退出 多窗口模式时调用此方法

Activity.onPictureInPictureChanged()  Activity进入/退出 picture-in-picture模式时调用此方法

          以上方法在Fragment同样存在

        应用适配Android N多窗口模式需要注意的就上面这些。

)的相关方法  可以查看官方文档http://developer.android.com/intl/zh-cn/preview/features/multi-window.html#running

二、消息推送增强

NotificationCompat.Builder.setGroup() 方法可以将相似的一些推送消息捆绑成一个通知。并且用户可以展开通知群中的每一个消息,单独地进行回复或者清除。

      1.推送可直接回复的消息

 RemoteInput.Builder来创建实例,这个类的构造函数接收一个String,系统会把这个string当做文本输入的键值key,用户回复后你的应用通过这个key取回文本内容来处理。


// Key for the string that's delivered in the action's intent
private static final String KEY_TEXT_REPLY = "key_text_reply";
String replyLabel = getResources().getString(R.string.reply_label);
RemoteInput remoteInput = new RemoteInput.Builder(KEY_TEXT_REPLY)
        .setLabel(replyLabel)
        .build();

addRemoteInput()方法把RemoteInput对象附加到action上

// Create the reply action and add the remote input
Notification.Action action =
        new Notification.Action.Builder(R.drawable.ic_reply_icon,
                getString(R.string.label), replyPendingIntent)
                .addRemoteInput(remoteInput)
                .build();

    最后,把action添加到Notification上推送出来就行。

/ Build the notification and add the action
Notification notification =
        new Notification.Builder(mContext)
                .setSmallIcon(R.drawable.ic_message)
                .setContentTitle(getString(R.string.title))
                .setContentText(getString(R.string.content))
                .addAction(action))
                .build();

// Issue the notification
NotificationManager notificationManager =
        NotificationManager.from(mContext);
notificationManager.notify(notificationId, notification);

这样,当你的消息被推送到通知栏的时候,Android N系统会提示用户这条消息可以进行回复了。

     2.取回用户回复的文本

     如题,刚刚发出了支持用户回复的通知,接下来如何取回用户回复的文本?

     从你之前定义的Action中,用户回复后的Intent跳转的Activity内部调用getResultsFromIntent()方法,该方法返回的bundle内包含用户回复的文本。

Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);

     取回文本用需要到对应的key,下文是取回代码示例。

// Obtain the intent that started this activity by calling
// Activity.getIntent() and pass it into this method to
// get the associated string.

private CharSequence getMessageText(Intent intent) {
    Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
    if (remoteInput != null) {
            return remoteInput.getCharSequence(KEY_TEXT_REPLY);
            }
    return null;
 }

某些社交聊天应用也许希望给用户提供之前的聊天记录,这样用户能更合理的在消息栏回复,那么可以去了解下

setRemoteInputHistory()方法。

3.推送消息组

    Android N系统中,Google建议开发者把相关的推送都捆绑起来成一个Group,这个跟Android Wear中的Notification Stacks概念相似。

     捆绑成group的通知组,还需要额外设置总结性的通知标题,用户可以逐级地展开消息通知,一直到可以展开单个消息的内容。

android 多 android多窗口模式_Android N 新特性_02


      如何创建一个推送消息组,并把每一条相似的消息都加到消息组内呢?

     首先,调用每个Notification的setGroup()方法为他们指定一个stack,给定确切的groupkey,然后就可以将消息发送到设备上了。

final static String GROUP_KEY_EMAILS = "group_key_emails";

// Build the notification, setting the group appropriately
Notification notif = new NotificationCompat.Builder(mContext)
         .setContentTitle("New mail from " + sender1)
         .setContentText(subject1)
         .setSmallIcon(R.drawable.new_mail)
         .setGroup(GROUP_KEY_EMAILS)
         .build();

// Issue the notification
NotificationManagerCompat notificationManager =
        NotificationManagerCompat.from(this);
notificationManager.notify(notificationId1, notif);

然后,当你把另外一个推送的通知跟上面那个一样设置相同的GroupKey的时候,它们就会被加入到同一个组里

Notification notif2 = new NotificationCompat.Builder(mContext)
         .setContentTitle("New mail from " + sender2)
         .setContentText(subject2)
         .setSmallIcon(R.drawable.new_mail)
         .setGroup(GROUP_KEY_EMAILS)
         .build();

notificationManager.notify(notificationId2, notif2);



消息栈中的消息是默认按时间顺序排列的,最近发布会显示在最上面,要修改消息顺序,可以调用setSortKey()方法来实现。

     就想一篇文章要有概述一样,消息组也可以用setGroupSummary()来添加一个概述的消息。

Bitmap largeIcon = BitmapFactory.decodeResource(getResources(),
        R.drawable.ic_large_icon);

// Create an InboxStyle notification
Notification summaryNotification = new NotificationCompat.Builder(mContext)
        .setContentTitle("2 new messages")
        .setSmallIcon(R.drawable.ic_small_icon)
        .setLargeIcon(largeIcon)
        .setStyle(new NotificationCompat.InboxStyle()
                .addLine("Alex Faaborg   Check this out")
                .addLine("Jeff Chang   Launch Party")
                .setBigContentTitle("2 new messages")
                .setSummaryText("johndoe@gmail.com"))
        .setGroup(GROUP_KEY_EMAILS)
        .setGroupSummary(true)
        .build();

notificationManager.notify(notificationId3, summaryNotification);

      Android N中熟知的多窗口模式与消息推送的改动大概就在上面了,总结的不对的地方欢迎指正,多谢。

      参考文档:http://developer.android.com/intl/zh-cn/preview/api-overview.html