Androiid 华为平板平行视界适配小结

文章讲述了在华为平板上进行平行视界适配过程中遇到的挑战,包括启动页与主界面的分屏逻辑、配置问题以及如何判断是否处于平行视界模式。通过修改配置文件、调整活动管理以及适配特定模式,作者最终解决了启动页和主界面的显示问题。
摘要由CSDN通过智能技术生成
华为官方适配平行视界的文档:文档中心
最近在做华为平板的平行视界下的适配工作,从一开始的小白到网上查资料踩坑,到现在逐步实现了想要的功能。提一个比较坑的一点,就是网上不少人写的判断是否是平行世界模式,用的是
String config = this.getResources().getConfiguration().toString();
return config.contains("hwMultiwindow-magic") || config.contains("miui-magic-windows");或是config.contains("hwMultiwindow-magic")。然而,这是错的!!!一直是false

真正对的写法是config.contains("hw-magic-windows");这个也是官网上说明了。文档中心

说下我遇到的功能需求。由于开发的App安装到华为平板上后,会默认开启平行视界模式,也就是在平板的设置-平行视界中能看到App的开关是开着的。所以,不得已进行适配平行视界。
而App的启动流程原先是启动页--->主界面,但是启动页中需要做各种操作,为整个App功能和主界面的功能做一些初始化。这里其实有个先后关联关系,这就要求,启动页的处理不能随随便便。

关于分屏适配的心路历程:因为适配前,App的启动逻辑就是启动页SplashActivity-->主界面MainActivity。且启动页是要关闭的。然后就想着,适配的话,就需要一个辅助页MainPageActivity。App一启动的时候是启动的辅助页,辅助页设置为全屏,然后1秒后跳转到启动页,跳转后两个界面就分屏了(我预想应该可以这样的)。因为官方文档上说的可以设置某个界面默认的启动方式为全屏,我就有了这个想法。但是实际测试发现,如果启动页是全屏,即使设置了
 "activityPairs": [ { "from": "com.cnki.android.cnkimoble.activity.MainPageActivity", "to": "com.cnki.android.cnkimoble.activity.SplashActivity" } ],
和
"Activities": [
          {
            "name": "com.cnki.android.cnkimoble.activity.MainPageActivity",
            "defaultFullScreen": "true"
          },
          {
            "name": "com.cnki.android.cnkimoble.activity.SplashActivity",
            "defaultFullScreen": "false"
          }
        ]

跳转到启动页后,并不会分屏,启动页依然是全屏。但是如果翻转为竖屏再翻转回来,就变成了分屏了。但是,这不是我想要的效果。
后来发现实在不行,就只好改为启动时双屏显示的方案。也就是
"defaultDualActivities": { "mainPages": "com.cnki.android.cnkimoble.activity.MainPageActivity", "relatedPage": "com.cnki.android.cnkimoble.activity.SplashActivity" },
。启动时的显示问题解决了,也就是启动双屏,然后SplashActivity跳转到MainActivity,且SplashActivity关闭(注意,这里埋了一个坑,后面说),MainActivity打开二级界面,这一系列的显示都是ok的,如自己想要的一样。

然而,从主界面的二级界面返回后,本来想着应该是辅助页和主界面分屏显示啊,结果,只剩一个主界面了,当然,它是半屏的,中间的那种。那,辅助页怎么显示不出来了呢。我郁闷了。由于这个App本身功能复杂,配置也是各种配置,有可能不知道哪个地方影响到了呢,或者本来就是这个样?于是,我新建了一个干净的Demo,仿照这个启动逻辑重新搞了一遍。结果发现,当主界面的二级界面关闭后,Demo里的辅助页和主界面是正常显示的,并不会像自己开发的App显示的只剩主界面半屏中间的那样。

于是,我猜测应该就是App配置影响到了。仔细检查了清单文件,发现了猫腻。主界面的配置是这样的:
<activity
    android:name="com.cnki.android.cnkimoble.activity.MainActivity"
    android:clearTaskOnLaunch="true"
    android:configChanges="keyboardHidden|orientation|screenSize|smallestScreenSize
       |screenLayout"
    android:label="@string/app_name"
    android:launchMode="singleTask"
    android:screenOrientation="unspecified"
    android:windowSoftInputMode="adjustPan">

</activity>

不寻常的配置有两项,android:clearTaskOnLaunch="true"和android:launchMode="singleTask"

而,android:clearTaskOnLaunch="true"这个就是启动的时候会把任务栈清空,也就是其他界面都移出去了,那么辅助页当然也被移出去了,所以,当二级界面回退到主界面时,只剩下主界面了,辅助页没有了。但是又有个问题,就是明明启动主界面时会把任务栈清空,那为啥那个时候辅助页还是存在的?界面显示正常啊。这应该是任务栈清空不会立即影响到界面,当需要重新显示辅助页时才会影响到,这里只是我的猜测。但这里不做深入讨论,毕竟现在我要把这个属性改一下。

android:clearTaskOnLaunch="false"
再重新运行,发现这个问题解决了。但后来发现,不是这个原因,貌似平板关机后重启,就没问题了。其实平行世界的这个系统功能还是不够稳定,不只我说,我看很多人也是吐槽,说功能还不稳定就放出来让用户用,而且还让开发者适配,这就坑到开发者了。

分屏显示时主界面退出后启动页重新创建的问题,用下面的代码解决:
Intent home = new Intent(Intent.ACTION_MAIN); home.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); home.addCategory(Intent.CATEGORY_HOME); startActivity(home);

适配过程中主要有几个点。
一、声明兼容平行视界模式
<meta-data
    android:name="EasyGoClient"
    android:value="true" />
下面这个不加貌似也没问题
<meta-data
    android:name="android.allow_multiple_resumed_activities"
    android:value="true"/>

二、easyGo.json的配置

{
  "easyGoVersion": "1.0",
  "client": "com.cnki.android.cnkimobile",
  "logicEntities": [
    {
      "head": {
        "function": "magicwindow",
        "required": "true"
      },
      "body": {
        "mode": "0",
        "defaultDualActivities": {
          "mainPages": "com.cnki.android.cnkimoble.activity.MainPageActivity",
          "relatedPage": "com.cnki.android.cnkimoble.activity.SplashActivity"
        },
        "activityPairs": [
          {
            "from": "com.cnki.android.cnkimoble.activity.MainActivity",
            "to": "*"
          }
        ],

        "UX": {
          "supportRotationUxCompat": "true",
          "isDraggable": "true",
          "supportDraggingToFullScreen": "PAD"
        }
      }
    }
  ]
}

"mode": "0",表示是购物模式,官网中也说明了。我的功能是在购物模式下才能很好的实现。

三、启动的双屏配置

配置文件中

"defaultDualActivities": { "mainPages": "com.cnki.android.cnkimoble.activity.MainPageActivity", "relatedPage": "com.cnki.android.cnkimoble.activity.SplashActivity" }

决定着,启动界面应该是MainPageActivity

所以就有了以下配置

<activity
    android:name="com.cnki.android.cnkimoble.activity.MainPageActivity"
    android:label="@string/app_name"
    >
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />

        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>
<activity
    android:name="com.cnki.android.cnkimoble.activity.SplashActivity"
    android:label="@string/app_name"
    android:screenOrientation="unspecified"
    android:windowSoftInputMode="adjustPan">
</activity>

而主界面

<activity
    android:name="com.cnki.android.cnkimoble.activity.MainActivity"
    android:clearTaskOnLaunch="true"
    android:configChanges="keyboardHidden|orientation|screenSize|smallestScreenSize
       |screenLayout"
    android:label="@string/app_name"
    android:launchMode="singleTask"
    android:screenOrientation="unspecified"
    android:windowSoftInputMode="adjustPan">

</activity>

注意,在适配平行视界之前,就是这个写法。有两点比较特殊,android:clearTaskOnLaunch="true"和android:launchMode="singleTask"

四、主界面退出时,App中调用了这个方法,来关闭。

/**
 * 退出程序关闭所有的Activity
 */
public static void finishActivitys() {
    LogSuperUtil.i(Constant.LogTag.advertise,"MyMainPage finish all activity",1);
    if(true) {
        Intent home = new Intent(Intent.ACTION_MAIN);
        home.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        home.addCategory(Intent.CATEGORY_HOME);
        getInstance().startActivity(home);
        //return;
    }
    for (int i = 0; i < mActivityList.size(); i++) {
        if (null != mActivityList.get(i).get()) {
            String activityName=mActivityList.get(i).get().getLocalClassName();
            if(activityName!=null&&activityName.equals(MainPageActivity.class.getName())) {

            }else {

            }
            LogSuperUtil.i(Constant.LogTag.advertise,i+" MyMainPage finish activity="+activityName);
            mActivityList.get(i).get().finish();
        }

    }
    mActivityList.clear();//这个必须有,因为有的地方判断MainActivity是否在运行要遍历mActivityList
}

五、对于解决我需求中的Bug的比较重要的知识点

/**
 * 判断是否处于平行视界
 * @return true/false
 */
protected boolean isInMagicWindow(){
   //String config = this.getResources().getConfiguration().toString();
   //return config.contains("hwMultiwindow-magic") || config.contains("miui-magic-windows");
   String config = this.getResources().getConfiguration().toString();
   boolean isInMagicWindow = config.contains("hw-magic-windows");//这个才是官网上说的判定标准
   return isInMagicWindow;
}
Intent home = new Intent(Intent.ACTION_MAIN);
home.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
home.addCategory(Intent.CATEGORY_HOME);
startActivity(home);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值