Android P专区免费开放 -- 同样的Android,不同的体验

听闻少年二字,当与平庸相斥。这篇文章主要讲述Android P专区免费开放 -- 同样的Android,不同的体验相关的知识,希望能为你提供帮助。
2018年3月8日,Google推出了android P Preview版本,并提供官方镜像下载。
 
为了让广大开发者能够及时了解Android P的新功能特性,提前为您的app进行良好适配,WeTest决定限时免费开放Android P Preview版本的远程调试及标准兼容功能,供开发者进行体验。
 
即日起,针对WeTest平台的Android P、Android Oreo专区,个人认证用户可免费获得30分钟/天远程调试、3次/天标准兼容测试额度;企业账户可获得60分钟/天远程调试、6次/天标准兼容测试额度。
 
 
此外,WeTest的技术专家就本次Android P的新特性,进行了一些简单的开发体验,供大家参考:

Android P专区免费开放 -- 同样的Android,不同的体验

文章图片

 
新功能特性抢先看
Android P的新功能特性集中在了UI、通知体验、室内定位、图像存储几个方面,解决了之前一直存在的痛点。例如WiFi RTT一定程度上弥补了蜂窝网络在室内环境下的定位问题,HEIC图像格式则重点解决了存储容量问题。同时,Android P也在通知丰富度及操作便捷性等功能方面有所增强和提升。
 
一、WiFi RTT功能——复杂地形精确导航
WiFi RTT功能是Android P新引入的一个功能,从原理上来说与蜂窝网络的定位原理一致,但这个功能极大的弥补了蜂窝网络在室内定位的短板,WiFi RTT将能够在室内提供高精度的定位,这是蜂窝网络很难做到的。
 
WiFi RTT是全新的功能,在android.net.wifi包下增加了rtt包,用于存放WiFi RTT相关类和接口。
 
WiFi RTT的API以WifiRttManager为核心,借助AP热点或WiFi,利用RTT原理完成测距,通过三个以上的测距点就能够准确地定位到设备所在位置。
 
WiFiRTTManager提供了测距接口,是一个异步测距操作,根据官方文档(https://developer.android.com/reference/android/net/wifi/rtt/WifiRttManager.html)说明,其测距接口如下:
void startRanging(RangingRequest request, RangingResultCallback callback, Handler handler);
 
注:  SDK Platforms Android P Preview Revision 1的相关接口定义与此不同,但实际的官方镜像中接口与此一致,开发者需要更新最新的Android P Preview Revision 2,此版本中Google已经修正该接口。
 
接口中,RangingRequest通过RangingRequest.Builder构建,RangingRequest.Builder构建出RangingRequest所需要的参数可以通过WiFiManager等系统服务获取到相关的内容,如  List< ScanResult> scanResults = wifiManager.getScanResults();
以下提供一个简单的测试Demo,以供参考:
private WifiRttManager wifiRttManager;
private WifiManager wifiManager;
 
@Override
protected void onCreate(Bundle savedInstanceState) {
      // ... ...
 
      if(getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_RTT)) {
              Object service = this.getApplicationContext().getSystemService(Context.WIFI_RTT_RANGING_SERVICE);
              if(service instanceof WifiRttManager) {
                      wifiRttManager= (WifiRttManager) service;
                      Log.i(TAG, "Get WifiRttManager Succ.");
              }
 
              wifiManager = (WifiManager) this.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
 
              IntentFilter wifiFileter = new IntentFilter();
              wifiFileter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
              wifiFileter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
              wifiFileter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
              registerReceiver(new WifiChangeReceiver(), wifiFileter);
      }
 
      // ... ...

 
private void startScanAPs() {
      wifiManager.setWifiEnabled(true);
      wifiManager.startScan();
}
 
class WifiChangeReceiver extends BroadcastReceiver {
      @RequiresApi(api = 28)
      @Override
      public void onReceive(Context context, Intent intent) {
              if (intent.getAction().equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
                      List< ScanResult> scanResults = wifiManager.getScanResults();
                      Log.i(TAG, "Wifi Scan size:" + scanResults.size());
                      for(ScanResult scanResult:  scanResults) {
                              Log.i(TAG, scanResult.toString());
                              RangingRequest.Builder builder = new RangingRequest.Builder();
                              builder.addAccessPoint(scanResult);
                              wifiRttManager.startRanging(builder.build(), new RangingResultCallback() {
                                      @SuppressLint("Override")
                                      @Override
                                      public void onRangingFailure(int i) {
                                              // TODO 
                                        }
                                      @SuppressLint("Override")
                                      @Override
                                      public void onRangingResults(List< RangingResult> list) {
                                              // TODO get result from list
 
                                              for(RangingResult result : list) {
                                                      Log.i(TAG, result.toString());
                                              }
                                      }
                              }, new Handler());
                      }
              }
      }
}
 
使用WiFi RTT时,需要在AndroidManifest.xml中增加如下声明:
< uses-feature android:name="android.hardware.wifi.rtt" />
 
通过上面的简单代码,就能够实现WiFi RTT的功能。
 
WiFi RTT功能适用于复杂地形的大型室内外场所,如商场、娱乐场所、大型休闲、游乐场等等,提供场所内的局部区域精确化导航等功能。相信在很快的时间内,就能够在各大地图应用内体验到这项便利功能,对于路痴、地图盲的伙伴们将是极大的福音。
 
二、显示剪切——支持刘海屏
随着iPhone X的推出,“刘海屏”达到了空前的高潮。Android P里提供了对异形屏幕的UI适配兼容方案,通过DisplayCutout类提供的相关接口,能够获取到屏幕中Cutout区域的信息。
 
借助DisplayCutout,可以获取到如下信息:
DisplayCutout displayCutout = view.getRootWindowInsets().getDisplayCutout();
if(displayCutout != null) {
      Region bounds = displayCutout.getBounds();
      Log.d(TAG, String.format("Bounds:%s", bounds.toString()));
      int top = displayCutout.getSafeInsetTop();
      int bottom = displayCutout.getSafeInsetBottom();
      int left = displayCutout.getSafeInsetLeft();
      int right = displayCutout.getSafeInsetRight();
      Log.d(TAG, String.format("Cutout edge:[left:%d, top:%d,right:%d, bottom:%d]", left, top, right, bottom));
}
 
public Region getBounds()能够获取到Cutout区域的所有信息,Region就是Cutout区域。
public int getSafeInsetTop()
public int getSafeInsetBottom()
public int getSafeInsetLeft()
public int getSafeInsetRight()

 
以上四个接口,可以获取到去除Cutout区域后的安全区域边界值。
 
通过上述数据,开发者能够精准的控制UI的绘制,避免将UI内容绘制到Cutout区域造成UI显示异常。
 
Android机器里,刘海屏目前还是极为罕见的Google为了方便开发者调试,在Android P Preview镜像中,特别提供了Cutout的支持,具体打开方式可以参考Google提供的特性说明文档cutout小节内容。
cutout小节(https://developer.android.com/preview/features.html#cutout)
 
如图所示,笔者使用手头的Pixel 2 XL体验了Android P的Cutout设置。
 
Android P专区免费开放 -- 同样的Android,不同的体验

文章图片

 
 
三、通知优化——操作更多样,内容更丰富
Android P在通知内容的丰富度和操作上做了优化。
 
最近的版本中,Android系统的通知管理方面一直优化升级,Android O提供了更细粒度的Channel功能,通知栏推送时需要指定NotificationChannel,用户可以对通知的Channel选择,只允许感兴趣的Channel推送的通知显示。通过通道设置、免打扰优化等方式,极大增强了消息体验。
 
增强消息体验
Android P继续改进和增强消息通知[v1]  。早在Android 7.0时,就提供了在通知中直接应答和输入,Android P对这一功能做了更多的增强。
 
Android P的通知中支持图像内容,可以通过setData()方法,给出消息的图像内容,在通知上展示給用户。
 
Android P同样简化了通知的配置形式。Android P中增加了Notification.Person类,用于区分同一个对话的参与者信息,如参与者的头像、URI等。根据官方说明,Android P中,通知消息的其他一些API,也使用Person替代之前的CharSequence。
 
简单的体验下新的API的开发:
NotificationChannel channel = new NotificationChannel("WtTestChannel",
                                              "WtTestChannel", NotificationManager.IMPORTANCE_DEFAULT);
channel.enableLights(true); // luncher icon right corner\'s point
channel.setLightColor(Color.RED); // read point
channel.setShowBadge(true); // whether show this channel notification on long press icon
 
Notification.Builder builder =
              new Notification.Builder(MainActivity.this,
                              "WtTestChannel");
Notification.Person p = new Notification.Person();
p.setName("WeTest");
p.setUri("http://cdn.wetest.qq.com/" +
              "ui/1.2.0/pc/static/image/newLogo-16042.png");
Notification.MessagingStyle messageStyle = new Notification.MessagingStyle(p);
Notification.MessagingStyle.Message message =
              new Notification.MessagingStyle.Message("WeTestMessage", 2000, p);
 
//show image
Uri image = Uri.parse(
              "http://cdn.wetest.qq.com/ui/1.2.0/pc/static/image/newLogo-16042.png");
message.setData("image/png", image);
messageStyle.addMessage(message);
builder.setStyle(messageStyle);
builder.setSmallIcon(R.mipmap.ic_launcher);
Notification notification = builder.build();
 
NotificationManager notifyManager =
              (NotificationManager) getSystemService(
                              MainActivity.this.getApplicationContext().NOTIFICATION_SERVICE);
 
 
notifyManager.createNotificationChannel(channel);
notifyManager.notify("WeTest", 1, notification);
 
通道设置、广播和免打扰优化
Android P中,重点做了内容丰富上的工作,同时也对Channel的设置方面做了一些简化处理。
 
Android O版本里,首次推出了NotificationChannel,开发者需要配置相应的Channel,才能够推送通知給用户。用户能够更加细粒度[v1]  的针对App的Channel选择,而不是禁止App的所有通知内容。
 
而在Android P中,对通知的管理做了进一步的优化,包括可以屏蔽通道组、提供新的广播类型和新的免打扰优先级。
 
屏蔽通道组:  用户可以在通知设置中屏蔽App的整个通道组。开发者可以通过isBlocked()来判断某个通道组是否被屏蔽了,并根据结果,不向已经被屏蔽的通道组发送任何通知。另外,开发者可以在App中使用新接口getNotificationChannelGroup()来查询当前的通道组设置。
 
新的广播类型:新广播类型是针对通道和通道组的功能增加的“通道(组)屏蔽状态变化”广播。开发者App中可以对所拥有的通道(组)接收广播,并根据具体广播内容作出动作。开发者可以通过NotificationManager,查看广播相关的具体信息。针对广播的动作可以通过Broadcasts查看具体的方法和信息。
 
免打扰优先级:  NotificationManager.Policy增加了两个新的优先级常量,PRIORITY_CATEGORY_ALARMS(警告优先),PRIORITY_CATEGORY_MEDIA_SYSTEM_OTHER  (媒体、系统和游戏声音优先)。
 
 
四、支持多摄像机和相机共享
近一段时间,双摄、多摄等机型纷纷面世。双摄及多摄提供了单摄像头所无法完成的能力,如无缝缩放、散景和立体视觉。Android P在这方面也提供了系统级的API支持。
 
Android P提供了系统API,支持从两个或者多个物理摄像头同步获取数据流。此前OEM厂商提供的双摄设备多是厂商自行定制系统实现,此时Android P推出了API,从系统层面上制定了API规范。
 
新的API提供了在不同相机之间切换逻辑数据流或混合数据流的调用能力。在捕捉延迟方面,提供新的会话参数,降低初始捕捉延迟。同时,提供相机共享能力,以解决在多种使用相机的场景下重复停止、开启相机流。闪光灯方面,Android P增加基于显示的闪光灯支持。光学防抖方面,Android P向开发者提供OIS时间戳,用于图像稳定性优化以及其他特效使用。
 
此外,Android P还支持外部USB/UVC相机,可以使用更强大的外置摄像头模组。
 
五、支持图像媒体后期处理
 
Android P引入了新的ImageDecoder,该类除了支持对各种图片格式的解码、缩放、裁剪之外,其强大之处在于支持对解码后的图像做后期处理(post-process),使用该功能可以添加复杂的自定义特效,比如圆角,或是将图片放在圆形像框中。编写后期处理回调函数,你可以添加任何绘图指令实现需要的效果。
 
此外,Android P原生支持GIF和WebP格式的动图,新增了AnimagedImageDrawable类,并被新增的解码器类ImageDecoder直接支持,用法跟矢量动画类AnimatedVectorDrawable类似,实现方式也类似,通过新增渲染线程和工作线程,不需要在UI线程处理动图更新,可以说是无痛使用,非常省心。
 
下面通过编写代码,显示一张gif图,并利用后期处理机制,在图像中间绘制一个绿色的实心圆。
 
Android P专区免费开放 -- 同样的Android,不同的体验

文章图片

 
final ImageView image = (ImageView) findViewById(R.id.image);
File gifFile = new File("/data/local/tmp/test.gif");
if (!gifFile.exists()) {
    Log.d(TAG, "gifFile is not exsited!");
    return;
}
 
ImageDecoder.Source source = ImageDecoder.createSource(gifFile);
try {
      d = ImageDecoder.decodeDrawable(source, new ImageDecoder.OnHeaderDecodedListener() {
              @Override
              public void onHeaderDecoded(ImageDecoder imageDecoder, final ImageDecoder.ImageInfo imageInfo, ImageDecoder.Source source) {
                      imageDecoder.setPostProcessor(new PostProcessor() {
                              @Override
                              public int onPostProcess(Canvas canvas) {
                                      int w = imageInfo.getSize().getWidth();
                                      int h = imageInfo.getSize().getHeight();
                                      Paint paint = new Paint();
                                      paint.setAntiAlias(true);
                                      paint.setColor(Color.GREEN);
                                      canvas.drawCircle(w/2, h/2, h/4, new Paint(paint));
                                      return 0;
                              }
                      });
              }
      });
      image.setVisibility(View.VISIBLE);
      image.setImageDrawable(d);
} catch (IOException e){
      Log.d(TAG, e.toString());
}
Button button = (Button) findViewById(R.id.buttonText);
button.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View view) {
              if (d != null & & d instanceof AnimatedImageDrawable) {
                      AnimatedImageDrawable ad = (AnimatedImageDrawable) d;
                      if (ad.isRunning()) {
                              Log.d(TAG, "stop running");
                              ad.stop();
                      } else {
                              Log.d(TAG, "start running");
                              ad.start();
                      }
              }
      }
});
 
六、支持HDR VP9和HEIF
Android P内置了对HDR VP9和HEIF(heic)图像编码的支持。HEIF是苹果在ios11推出的一种高效压缩格式,目前在IphoneX、Iphone 8、IPhone 8P上已经支持。该格式的压缩率更高,但是编码该格式需要硬件的支持,解码并不需要。最新的支持库中的HeifWriter支持从YUV字节缓冲区、Surface或是Bitmap类转换为HEIF格式的静态图像。
 
Android P新引入了MediaPlayer2,支持DataSourceDesc创建的播放列表。
 
功能优化提升一览
一、神经网络API 1.1
在前不久发布的Android 8.1 (API level 27)上,Google首次在Android平台上推出了神经网络API,这意味着我们的Android机器智能化水平又提高了一大步。而本次Android P,进一步丰富了神经网络的支持,不仅对之前的相关API进行了优化,并且提供了9个新的操作,为具体的数据操作方面提供了更深入的支持。
 
 
二、改进表单自动填充
Android 8.0(API等级26)中引入了自动填充框架,这使得在应用中填写表单变得更加容易。 Android P引入了自动填充服务并实现了多项改进,得以在填写表单时进一步增强用户体验。
 
 
三、安全增强
Android P引入了许多新的安全功能,包括统一的指纹验证对话框和敏感交易的高确信度的用户确认。应用程序内的指纹认证UI也将会更加一致。
 
统一的指纹验证对话框
如果第三方APP想要使用指纹,Android系统框架为应用提供了指纹认证对话框,该功能可以提供统一的外观和使用体验,用户使用起来更放心。如果您的程序还在使用FingerprintManager,现在改用FingerprintDialog替代吧,系统来提供对话框显示。对了,在使用FingerprintDialog之前,别忘了调用hasSystemFeature()方法检查手机设备是否支持指纹。
 
敏感交易的高确信度的用户确认
Android P系统提供了受保护的确认API,借助这组全新的API,应用可以使用ConfirmationDialog对话框向用户提示,请求用户批准一条简短的声明, 该声明允许应用提醒用户,即将完成一笔敏感交易,例如支付。
 
如果用户接受声明,应用将会收到一条key-hash的消息认证码(HMAC),该签名由TEE产生,以保护用于输入和认证对话框的显示。该签名表示用于已经看到了声明并同意了。
 
硬件安全模块
Android P还提供了StrongBox Keymaster(强力沙盒秘钥大师),一个存储在硬件安全模块的具体实现。在这个硬件安全模块中有自己的CPU、安全存储空间,真随机数生成器,以及额外的机制抵御应用被篡改或是未授权应用的恶意加载。当检查存储在StrongBox Keymaster中的密钥时,系统通过可信执行环境(TEE)确认密钥的完整性。为了降低能耗,StrongBox支持了一组算法和不同长度的秘钥:
●  RSA 2048
●  AES 128 and 256
●  ECDSA P-256
●  HMAC-SHA256 (支持8字节到64字节任意秘钥长度)
【Android P专区免费开放 -- 同样的Android,不同的体验】

    推荐阅读