美文网首页
安卓各编译版本差异汇总

安卓各编译版本差异汇总

作者: 鹈鹕醍醐 | 来源:发表于2018-07-09 16:43 被阅读29次

安卓版本适配信息汇总,最后更新于2019-1-24 18:11:25,持续收集中


  • 1:安卓4.4 API-19

    • 1.1:应用支持全屏模式,也就是常说的 沉浸式 ,这一块踩坑存在bug
    • 1.2:虚拟按键可隐藏,既然沉浸式底部导航栏跟着支持了,那就顺路把相关控制API也暴露给开发者
    • 1.3:为了加强WebView的功能,Google引入了Chromium内核。但仍然还是存在 编辑的bug

  • 2:安卓5.0 API-21

    • 2.1:ART androidRunTime取代 Dalvik 成为平台默认设置,ART采用预先编译技术,改进了垃圾回收机制与调试支持

    • 2.2:Material Design设计规范,以及Appcompat-V7 RecyclerView-V7 CardView-V7等框架,在UI上突出的变化还有 SharedElementAnimation elevation等。

    • 2.3:提升用户隐私的安全性,弃用activityManager.getRecentTask()方法。对于向后兼容性,此方法仍会返回它的一小部分数据,包括应用自己的任务和可能的一些其他非敏感任务(如首页)。如果你的应用使用此方法检索它自己的任务,则改用getAppTasks检索信息

    • 2.4:禁用隐式意图启动服务,运行时会直接抛出IllegalArgumentException异常

      Intent intent = new Intent();过时禁用
      intent.setAction("com.example.myapplication");
      startService(intent);
      只能使用显式意图
      Intent intent = new Intent("com.example.myapplication");
      
    • 2.5:Notification模块不支持设置了rgb通道的smallIcon,此bug 在后续版本已经修复,但是为了系统兼容性,建议开发者在安卓5.0及以上设备上更换smallIcon以达到版本一致性

    • 2.6:系统 默认会阻止混合内容和第三方 Cookie。要允许混合内容请调用 setMixedContentMode(),要允许第三方 Cookie,请调用setAcceptThirdPartyCookies()

    • 2.7:现在可以智能地选择要绘制的 HTML 文档部分。这个新的默认行为有助于减少内存占用和提升性能。如果您要一次渲染整个文档,可通过调用 enableSlowWholeDocumentDraw() 停用此优化。

    • 2.8:自定义权限必须保证唯一,使用不同秘钥签名的应用不能使用相同的自定义权限。如果用户设备上存在一个应用使用了相同的自定义权限,那么新的应用将无法安装

    • 2.9:移除了对锁定屏幕小部件的支持

    • 2.10:新增Intent.resolveActivity(*)对发起的意图进行设备匹配


  • 3:安卓6.0 API-23

    • 3.1:移除了Apachehttp支持包,如有需要手动引入。

      android {
          useLibrary 'org.apache.http.legacy'
      }
      
    • 3.2:废弃:FloatMathNotification.setLastEventInfo()

    • 3.3:移除了对设备本地硬件标识符的编程访问权。WifiInfo.getMacAddress()方法和 BluetoothAdapter.getAddress() 方法现在会返回常量值 02:00:00:00:00:00。如果需要通过蓝牙和wifi扫描访问外部设备的硬件标识符,应用必须拥有 ACCESS_FINE_LOCATIONACCESS_COARSE_LOCATION 权限。

    • 3.4:音频管理器变更:不再支持通过 AudioManager 类直接设置音量或将特定音频流静音。setStreamSolo()方法弃用,改为requestAudioFocus() 方法。setStreamMute() 方法弃用,改为adjustStreamVolume() 并传入方向值 ADJUST_MUTE/ ADJUST_UNMUTE

    • 3.5:APK 验证更为严格。如果在清单中声明的文件在 APK 中并不存在,该 APK 将被视为已损坏。移除任何内容后必须重新签署 APK。

    • 3.6:运行时权限管理,谷歌借鉴了苹果 和国内厂商的优化经验,对应用的权限不再一刀切,而是把相关权限分成了三组

      权限名称 权限说明
      SYSTEM_ALERT_WINDOW 设置悬浮窗,TYPE_SYSTEM_ALERT已失效
      WRITE_SETTINGS 修改系统设置
      • 敏感权限 运行时申请,如果没有适配会直接抛出异常,许可状态会保存
      权限组 权限名称 介绍
      CALENDAR android.permission.READ_CALENDAR 读取系统日历
      android.permission.WRITE_CALENDAR 写入系统日历
      CAMERA android.permission.CAMERA 相机权限
      CONTACTS android.permission.READ_CONTACTS 读取联系人
      android.permission.WRITE_CONTACTS 写入联系人
      android.permission.GET_ACCOUNTS 读取账号
      LOCATION android.permission.ACCESS_FINE_LOCATION 获取精准位置
      android.permission.ACCESS_COARSE_LOCATION 获取大概位置
      MICROPHONE android.permission.RECORD_AUDIO 录音
      PHONE android.permission.READ_PHONE_STATE 获取手机信息
      android.permission.CALL_PHONE 打电话,不建议使用
      android.permission.READ_CALL_LOG 读取通话记录
      android.permission.WRITE_CALL_LOG 写入通话记录
      android.permission.PROCESS_OUTGOING_CALLS 监听、控制、取消呼出电话的权限
      android.permission.USE_SIP 使用sip(会话发起协议)网络电话
      android.permission.ADD_VOICEMAIL 添加系统中的语音邮件
      SENSORS android.permission.BODY_SENSOR 使用生命体征相关传感器
      SMS android.permission.SEND_SMS 发送短信
      android.permission.RECEIVE_SMS 接收短信
      android.permission.READ_SMS 读取短信
      android.permission.RECEIVE_WAP_PUSH 接收WapPush信息
      android.permission.RECEIVE_MMS 接收彩信
      android.permission.READ_CELL_BROADCASTS 不存在的权限
      STORAGE android.permission.READ_EXTERNAL_STORAGE 读取存储
      android.permission.WRITE_EXTERNAL_STORAGE 写入存储

      运行时权限共9组,同一组下如果有一个权限被允许,其它权限会自动被允许。
      开发时应减少申请权限的次数,以避免交互被打断。对于敏感权限可用intent来代替,让其它应用去处理

  • 4:安卓7.0 API-24

    • 4.1:应用分屏,支持java8

    • 4.2:Notification.Builder通知消息可以通过setShowWhen()设置定时显示

    • 4.3:删除了三个常用隐式广播 : CONNECTIVITY_ACTIONACTION_NEW_PICTUREACTION_NEW_VIDEO 。因为这些广播可能会一次唤醒多个应用的后台进程,消耗内存和电池

    • 4.4:优化了SurfaceView,使其在视频播放和3D方面表现更优于TextureView

    • 4.5:APK signature scheme v2,android 7.0 新引入应用签名方案,它能提供更快的应用安装时间和更多针对未授权 APK 文件更改的保护。

    • 4.6:StrictMode API政策禁止在您的应用外部公开file:// URI。如果启动一个包含文件 URI 的intent会抛出FileUriExposedException异常。受此影响的有拍照图片选择,下载apk安装等功能。要在应用间共享文件,您应发送一项content:// URI,并授予 URI 临时访问权限。

      拍照intent示例:
      Intent intentCamera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
      添加这一句表示对目标应用临时授权该Uri所代表的文件
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        intentCamera.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
      }
      将拍照结果保存至photo_file的Uri中,不保留在相册中
      intentCamera.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
      activity.startActivityForResult(intentCamera, requestCode);
      
      安装APK intent如下
      Intent installIntent = new Intent(Intent.ACTION_VIEW));
      installIntent.addCategory(Intent.CATEGORY_DEFAULT);
      installIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
      
      if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
        String auth = null;
        PackageManager manager = context.getPackageManager();
        PackageInfo packageInfo = manager.getPackageInfo(packageName, PackageManager.GET_PROVIDERS);
        for (ProviderInfo provider : packageInfo.providers) {
           if ("FileProvider".equals(provider.name) && provider.authority.endsWith(".update.file_provider")) {
              auth = provider.authority;
              break;
            }
         }
         Uri uriForFile = FileProvider.getUriForFile(context, auth, apkFile);
         installIntent.setDataAndType(uriForFile, "application/vnd.android.package-archive");
         installIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
      } else {
        installIntent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive");
      }
      context.startActivity(installIntent);
      
    • 4.7:加密库 Crypto废弃 将密码作为随机数生成器的种子换算出密钥 key这种做法已经被认定为是不安全的。相关的 Crypto provider 和 SHA1PRNG 算法同时废弃掉了,并计划在后续的 SDK 中完全移除相关的库,如下是官方给出的解决方案:

        给出字符串的密码
       String password = "password";  
      
        密钥的比特位数,注意这里是比特位数
        AES 支持 128、192 和 256 比特长度的密钥
       int keyLength = 256; 
      
        盐值的字节数组长度,注意这里是字节数组的长度
        其长度值需要和最终输出的密钥字节数组长度一致
        由于这里密钥的长度是 256 比特,则最终密钥将以 256/8 = 32 位长度的字节数组存在
        所以盐值的字节数组长度也应该是 32
       int saltLength = 32;
       byte[] salt;
      
        先获取一个随机的盐值
        你需要将此次生成的盐值保存到磁盘上下次再从字符串换算密钥时传入
        如果盐值不一致将导致换算的密钥值不同
        保存密钥的逻辑官方并没写,需要自行实现
       SecureRandom random = new SecureRandom();  
       byte[] salt = new byte[saltLength];  
       random.nextBytes(salt);  
      
        将密码明文、盐值等使用新的方法换算密钥
       int iterationCount = 1000;
       KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt,iterationCount, keyLength);  
       SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");  
      
        到这里你就能拿到一个安全的密钥了
       byte[] keyBytes = keyFactory.generateSecret(keySpec).getEncoded();  
       SecretKey key = new SecretKeySpec(keyBytes, "AES");
      

  • 5:安卓8.0 API-26 (8.1 API-27)

    • 5.1:roundedIcon 自适应图标,在manifest文件中额外提供圆形应用icon
      <application
          android:name=".App"
          android:icon="@mipmap/ic_launcher"
          android:roundIcon="@mipmap/ic_launcher_round"
      ......
      
    • 5.2:PHONE权限组新增两个权限
      • ANSWER_PHONE_CALLS:允许接听呼入电话。在应用中使用 acceptRingingCall()函数处理呼入电话。
      • READ_PHONE_NUMBERS:允许应用读取设备中存储的电话号码。
    • 5.3:安卓8.0中,Notification的通知渠道。用户可以根据渠道来屏蔽一些不想要的通知
      void setNotifyChannel(NotificationManager manager, NotificationCompat.Builder builder, String channeId, String channelName) {
          if (TextUtils.isEmpty(channeId)||TextUtils.isEmpty(channelName)){
              L.e("NotifyCompat:  ".concat("安卓8.0的通知兼容库中 channeId 与 channelName 不能为empty"));
          }
          if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
              //第三个参数设置通知的优先级别
              NotificationChannel channel = new NotificationChannel(channeId, channelName, NotificationManager.IMPORTANCE_DEFAULT);
              channel.canBypassDnd();//是否可以绕过请勿打扰模式
              channel.canShowBadge();//是否可以显示icon角标
              channel.enableLights(true);//是否显示通知闪灯
              channel.enableVibration(true);//收到小时时震动提示
              channel.setBypassDnd(true);//设置绕过免打扰
              channel.setLockscreenVisibility(NotificationCompat.VISIBILITY_SECRET);
              channel.setLightColor(Color.RED);//设置闪光灯颜色
              channel.getAudioAttributes();//获取设置铃声设置
              channel.setVibrationPattern(new long[]{100, 200, 100});//设置震动模式
              channel.shouldShowLights();//是否会闪光
              if (manager != null) {
                  manager.createNotificationChannel(channel);    //manager 与channel关联
              }
              if (builder != null) {
                  builder.setChannelId(channeId);//Notification 与channel关联
              }
          }
      }
      
    • 5.4:新增普通权限:REQUEST_INSTALL_PACKAGES安装未知来源应用,也可以使用 canRequestPackageInstalls()查询是否有此权限,如果没有的话使用Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES这个action将用户引导至安装未知应用权限界面去授权。
      private void installAPK(){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
          boolean hasInstallPermission = getPackageManager().canRequestPackageInstalls();
          if (hasInstallPermission) {
              //安装应用
          } else {
              //跳转至“安装未知应用”权限界面,引导用户开启权限
              Uri selfPackageUri = Uri.parse("package:" + this.getPackageName());
              Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, selfPackageUri);
              startActivityForResult(intent, REQUEST_CODE_UNKNOWN_APP);
          }
        }else {
          //安装应用
        }
      }
      
    • 5.5:SharedPreferences不能使用MODE_WORLD_READABLE,请修改为MODE_PRIVATE
    • 5.6:新的广播接收器限制导致静态广播无法正常接收,应使用动态广播代替静态广播
    • 5.7:Only fullscreen opaque activities can request orientation,在Android 8.0上非全屏透明页面不允许设置方向(8.1以上谷歌就修复去掉了这个限制)

      解决方案1:在manifest中去掉此Activity的screenOrientation属性
      解决方案2:在此Activity的style里设置<item name="android:windowIsTranslucent">false</item>
      解决方案3:使用Dialog/DialogFragment/Popwindow代替此Activity。


  • 6:安卓9.0 API-28

    • 6.1:限制明文流量的网络请求,非加密的流量请求会被系统禁止掉
      解决方案:在xml目录新建文件network_security_config.xml
      <?xml version="1.0" encoding="utf-8"?>
        <network-security-config>
        <base-config cleartextTrafficPermitted="true" />
      </network-security-config>
      
      在manifest清单文件application节点配置android:networkSecurityConfig="@xml/network_security_config"
    • 6.2:java.lang.IllegalArgumentException: Invalid Region.Op - only INTERSECT and DIFFERENCE are allowed
      安卓9.0对canvas#clipPath()中的Region.Op做了限制只能使用INTERSECT或者DIFFERENCE。
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
       canvas.clipPath(mPath);
      } else {
       canvas.clipPath(mPath, Region.Op.REPLACE);
      }
      

相关文章

网友评论

      本文标题:安卓各编译版本差异汇总

      本文链接:https://www.haomeiwen.com/subject/dtqtpftx.html