相关链接: Android各版本适配之6.0
Android各版本适配之7.0
Notification.setLatestEventInfo弃用和替代方法

●安装apk的权限

首先第一步:我们需要在清单文件中添加一项权限 <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" /> 
有了这个权限之后,安装apk时判断:
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && !getPackageManager().canRequestPackageInstalls()){   PermissionUtil.requestPermissions(this,PermissionUtil.PERMISSION_INSTALL_PACKAGES_CODE, Manifest.permission.REQUEST_INSTALL_PACKAGES);}

具体权限管理请移步文章开头的6.0的权限管理文章查看。

通知栏的适配

Android O版本对通知做了规范性的控制,强制用户在发送通知的时候,对通知进行系统性的管理,新增了channel渠道功能:

private String Notification_ID = "5";private String Notification_CHANNEL_1 = "channel5";

private void showNotification(long cancelTime, String text) {   try {      Context app = context.getApplicationContext();      NotificationManager nm = (NotificationManager) app            .getSystemService(Context.NOTIFICATION_SERVICE);      final int id = Integer.MAX_VALUE / 13 + 1;      nm.cancel(id);      long when = System.currentTimeMillis();      Notification notification;      PendingIntent pi = PendingIntent.getActivity(app, 0, new Intent(), 0);      if(Build.VERSION.SDK_INT>= Build.VERSION_CODES.O){         NotificationChannel               channel = new NotificationChannel(String.valueOf(Notification_ID), Notification_CHANNEL_1, NotificationManager.IMPORTANCE_LOW);         channel.enableLights(true);//是否在桌面icon右上角展示小红点         channel.setLightColor(Color.GREEN);//小红点颜色         channel.setShowBadge(true); //是否在久按桌面图标时显示此渠道的通知         nm.createNotificationChannel(channel);         notification = new Notification.Builder(context)               .setChannelId(String.valueOf(Notification_ID))//该句适配android 8.0 版本               .setSmallIcon(notifyIcon)               .setContentTitle(notifyTitle)               .setTicker(text)               .setContentText(text)               .setWhen(when)               .setContentIntent(pi).setNumber(0)               .getNotification();         notification.flags |= Notification.FLAG_AUTO_CANCEL;      }else {         notification = new Notification.Builder(context)               .setSmallIcon(notifyIcon)               .setContentTitle(notifyTitle)               .setTicker(text)               .setContentText(text)               .setContentIntent(pi).setNumber(0)               .setWhen(when)               .getNotification();         notification.flags |= Notification.FLAG_AUTO_CANCEL;      }      nm.notify(id, notification);      if (cancelTime > 0) {         Message msg = new Message();         msg.what = MSG_CANCEL_NOTIFY;         msg.obj = nm;         msg.arg1 = id;         UIHandler.sendMessageDelayed(msg, cancelTime, this);      }   } catch (Exception e) {      e.printStackTrace();   }}
这样就会在8.0系统上弹出通知了。当然还需要及时的关闭通知,当更新进度条加载完成或者其他时候
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    //关闭通知通道
    notificationManager.deleteNotificationChannel("1");
}
悬浮框(7.0,8.0会崩溃) 在一些广播中需要弹出对话框的应用场景,没有依附的activity,这个时候就可以用悬浮窗。 在Android系统中,如果应用需要弹出一个悬浮窗口,就需要申请一项特殊权限“

Android O之前的系统中申请了该权限后,再给对应的window设置type:WindowManager.LayoutParams.TYPE_SYSTEM_ALERT悬浮窗口就可以显示出来。但是在Android O的系统中,google规定申请"android.permission.SYSTEM_ALERT_WINDOW"权限的应用需要给悬浮窗设置type:WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY.

悬浮窗口才能显示出来,如果不设置该TYPE,会Crash,8.0代码修改如下:

public static void showLogoutDialog(final Context context) {    AlertDialog.Builder builder = new AlertDialog.Builder(context);    View view = View.inflate(context, R.layout.dialog_logout, null);    builder.setView(view);    final AlertDialog dialog = builder.create();        //设置弹出全局对话框,但是这句话并不能解决在android的其他手机上能弹出来(例如用户华为p10 就无法弹框)    // dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_TOAST);        //只有这样才能弹框    if (Build.VERSION.SDK_INT>=26) {//8.0新特性        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);    }else{        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);    }    dialog.show();}
另外,6.0后需要申请悬浮窗权限,属于特殊权限,关于此权限的申请请看文章开头的6.0的适配文章链接;
透明Activity报错

Android 8.0透明Activity报错 "Only fullscreen activities can request orientation"

1、分析问题

首先,我的代码是这样的: 
style.xml

  • AndroidManifest.xml
<activity    android:name=".appmanager.mianframe.UsagePermissionGuideActivity"    android:launchMode="singleInstance"    android:screenOrientation="portrait"    android:theme="@style/app_transparent_activity"/>

从上面可以看出,我的activity是一个状态栏透明并且背景透明的activity。在26的编译版本时是可以正常的使用的,但是当把编译版本升级到27时,就会出现”Only fullscreen activities can request orientation”异常。这是google出于安全的考虑,对android8.0以后的版本做的处理,当一个Activity固定方向并且是透明的,在8.0以后的版本中就会抛出异常。相关源码如下:

Entry ent = AttributeCache.instance().get(packageName,realTheme, com.android.internal.R.styleable.Window, userId);final boolean translucent = ent != null && (ent.array.getBoolean(com.android.internal.R.styleable.Window_windowIsTranslucent, false)|| (!ent.array.hasValue(                com.android.internal.R.styleable.Window_windowIsTranslucent) &&  ent.array.getBoolean(com.android.internal.R.styleable.Window_windowSwipeToDismiss,false)));fullscreen = ent != null && !ent.array.getBoolean(com.android.internal.R.styleable.Window_windowIsFloating, false) && !translucent;fullscreen = ent != null && !ActivityInfo.isTranslucentOrFloating(ent.array);noDisplay = ent != null && ent.array.getBoolean(com.android.internal.R.styleable.Window_windowNoDisplay, false);if (ActivityInfo.isFixedOrientation(requestedOrientation) && !fullscreen && appInfo.targetSdkVersion >= O) {    throw new IllegalStateException("Only fullscreen activities can request orientation");}

上面是27的源码片段,通过上面我们可以看出当三个条件同时满足的时候,系统会抛出”Only fullscreen activities can request orientation”异常。先分别来说说这三个条件都表示什么意思:

  1. ActivityInfo.isFixedOrientation(requestedOrientation) —— 表示判断当前的|Activity是否固定了方向
  2. fullscreen —— 表示Activity是否是透明的或者是否悬浮在Activity上,是透明的或者悬浮在Activity上fullscreen就等于false
  3. appInfo.targetSdkVersion >= O —— 表示版本号大于等于26

当以上的三个条件同时满足的时候,系统框架就会抛出异常。

2、解决问题的方法

这个问题在最新的SDK中已经修复,我们在API Level 27的设备上已经无法重现,但我们手头的API Level 26的设备还是能重现。而且根据上面的代码来看,如果想保留当前Activity的style,“isTranslucentOrFloating”的逻辑根本没法绕过,所以想绕开很难,目前能想到的大概两个方向:

  1. 1.推迟SDK升级,等官方修复被大多数设备采用;
  2. 2.升级SDK,但重构一下代码,看看已有的非“fullscreen” Activity是不是都是必要的,例如用Fragment实现周围半透明效果,能不能直接把Fragment加入到当前Activity(当然Detach Fragment是有重绘View的开销的)。
  3. 3.使用Dialog代替透明的Activity
  4. 4.不固定Activity的方向
  5. 5.使用不透明且不是悬浮的主题(我采用此解决办法,8.0以后改为不透明不悬浮)

更多相关文章

  1. 关闭Android(安卓)root权限
  2. Android(安卓)6.0权限使用详解
  3. Android(安卓)7+的一些报错
  4. android WindowManager 应用内部悬浮窗口总结
  5. Android-sharedUserId数据权限
  6. Android(安卓)累计未读通知的数量
  7. Android应用程序组件Content Provider的共享数据更新通知机制分
  8. android 学习笔记3--静默安装功能的实现
  9. Android应用程序获取ROOT权限的方法

随机推荐

  1. mysql 数据库自增id 的总结
  2. 最近升级mysql5.7出现下面问题,ORDER BY c
  3. win server 2008 R2 已有apache 、mysql,
  4. mysql必知必会(一、数据库基础知识)
  5. mysql没有返回正确的值
  6. 配置Mysql远程连接
  7. mySQL:按给定的ID字符串排序ID? (为分层数据
  8. MySQL中间件之ProxySQL(12):禁止多路路由
  9. 可以在$ _SESSION中保存大量信息吗?
  10. 【动软.Net代码生成器】连接MySQL生成C#