Android适配8.0的坑

无法安装更新APK

经过搜索发现我们在AndroidManifest新增一个权限

<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />

异常: Only fullscreen opaque activities can request orientation

最近我升级到27之后发现突然分享界面报错,类似下面这种

 java.lang.IllegalStateException: Only fullscreen activities can request orientation

最后发现是因为调用这样的代码

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

经过搜索发现26的增加设置方向的判断

public static boolean isTranslucentOrFloating(TypedArray attributes) { 
    final boolean isTranslucent = attributes.getBoolean(com.android.internal.R.styleable.Window_windowIsTranslucent, false); 
    final boolean isSwipeToDismiss = !attributes.hasValue( com.android.internal.R.styleable.Window_windowIsTranslucent) 
                                     && attributes.getBoolean( com.android.internal.R.styleable.Window_windowSwipeToDismiss, false); 
    final boolean isFloating = attributes.getBoolean(com.android.internal.R.styleable.Window_windowIsFloating, false);  
    return isFloating || isTranslucent || isSwipeToDismiss;    
}

根据上面的定义,如果一个Activity的Style符合下面三个条件之一,认为不是“fullscreen”:

  1. “windowIsTranslucent”为true;
  2. “windowIsTranslucent”为false,但“windowSwipeToDismiss”为true;
  3. “windowIsFloating“为true;

综上可见,这个改动的目的是想阻止非全屏的Activity锁定屏幕旋转,因为当前Activity是透明的,浮动的或可滑动取消的,是否锁屏应该由全屏的Activity决定,而不是并没有全部占据屏幕的Activity决定。

解决方法:
只要你设置不符合上面三个条件即可,而且这个坑27已经没有了。

定位相关

为降低功耗,无论应用的目标 SDK 版本为何,Android 8.0 都会对后台应用检索用户当前位置的频率进行限制。

如果您的应用在后台运行时依赖实时提醒或运动检测,这一位置检索行为就显得特别重要,必须紧记。

重要说明:作为起点,我们只允许后台应用每小时接收几次位置更新。我们将在整个预览版阶段继续根据系统影响和开发者的反馈优化位置更新间隔。
详细可以点开这个官方说明
也就是如果持续的定位需求,必须通过一个通知开启一个前台服务
解决方法:
我是如此写的(语言为Kotlin),其实就是很简单的开启一个前台服务

class LocationForegoundService : Service() {

    private val mBinder = LocalBinder()

    private var channel:NotificationChannel ?= null

    inner class LocalBinder : Binder() {
        fun getService(): LocationForegoundService = this@LocationForegoundService
    }

    override fun onBind(intent: Intent): IBinder {
        return mBinder
    }

    override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
        //Android O上才显示通知栏
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            showNotify()
        }
        return super.onStartCommand(intent, flags, startId)
    }

    //显示通知栏
    private fun showNotify() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            if (channel == null){
                channel = createNotificationChannel()
            }
            val builder = NotificationCompat.Builder(applicationContext, packageName)
            val nfIntent = Intent(this, MainActivity::class.java)
            builder.setContentIntent(PendingIntent.getActivity(this, 0, nfIntent, 0))
                    .setLargeIcon(BitmapFactory.decodeResource(this.resources, R.mipmap.ic_launcher))
                    .setSmallIcon(R.drawable.push_notification_icon)
                    .setContentTitle("正在后台定位")
                    .setContentText("定位进行中")
                    .setWhen(System.currentTimeMillis())
            val notification = builder.build()
            //调用这个方法把服务设置成前台服务
            startForeground(110, notification)
        }
    }


    @TargetApi(Build.VERSION_CODES.O)
    private fun createNotificationChannel(): NotificationChannel {
        val channel = NotificationChannel(packageName,
                "",
                NotificationManager.IMPORTANCE_HIGH)
        // 获取NotificationManager
        val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE)
                as NotificationManager
        // 创建通知渠道
        notificationManager.createNotificationChannel(channel)
        return channel
    }

}
    原文作者:辩护人
    原文地址: https://www.jianshu.com/p/851c3197a808
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞