Android ROM适配
Android是开源的,不同的手机厂商都有自己定制的系统,所以这就给开发者带来了ROM适配难题。在一些群里面经常看到有人因为手机适配问题,说这个手机坑,那个手机坑,其实那是没有对ROM定制系统的一些变更了解,导致了盲目的说出这些指责的话。如果你熟悉了,也就会少走很多弯路。下面这篇文章就来讲一下几个主流手机的ROM适配问题。
一、手机平台相关文档
(一)小米
1、小米开发者文档
2、开发人员必看:《小米应用开发者文档》
在这里可以找到在小米手机上开发、分发应用的相关文档~
3、常见问题
4、小米帐号场景化登录
5、技术文档
(二)华为
1、 华为开发者文档
2、华为部分设备不打印Log
部分的华为设备工程模式下log是关闭的,华为部分设备不打印Log的解决方案:
1.如果是华为手机,进入拨号界面输入:*#*#2846579#*#*进入页面设置。
2.如果是华为pad,进入计算器输入:()()2846579()()= 进入页面设置。
3、华为手机获取拍照权限后拍照,返回值为空
问题起源:
开发中遇到了需要拍照和从图库中选择图片展示并上传的功能,其他手机测试没问题,华为手机获取拍照权限后拍照,返回值为空。
问题分析:
原来是华为在7.0以后的系统中,对于拍照后返回的图片也做了权限处理。所以说,华为7.0在拍照的时候,不仅要拿到拍照 CAMERA
的权限,还要拿到读写文件的权限 WRITE_EXTERNAL_STORAGE
。
解决方法部分代码如下:
//声明两个常量
public static final int MY_PERMISSIONS_REQUEST_CALL_PHONE = 0x0001;
public static final int MY_PERMISSIONS_REQUEST_CALL_PHONE2 = 0x0002;
//设置权限
public void setTakePhonePermissions(Context context) {
if (Build.VERSION.SDK_INT >= 23) {
int checkCallPhonePermission = ContextCompat.checkSelfPermission(context,
Manifest.permission.CAMERA);
if (checkCallPhonePermission != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(context, new String[]{Manifest.permission.CAMERA,}
, MY_PERMISSIONS_REQUEST_CALL_PHONE);
} else if (ContextCompat.checkSelfPermission(context,
Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(context,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA},
MY_PERMISSIONS_REQUEST_CALL_PHONE2);
} else {
takePhoto();
}
//小于23的不需要动态权限
} else {
takePhoto();
}
}
4、华为Android7.0手机打开摄像头拍照闪退问题。
5、华为手机Android8.0 使用代码安装APK闪退问题
更新版本APK自动安装的时候,在安卓6.0、7.0下都OK,唯独在华为安卓8.0手机闪退。
解决方案: 只要在Mainfest.xml 中加入请求安装权限就OK了
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
- ★★ 关于闪退的小结:
- 在Android 7.0(及以上)手机开启拍照功能,既要申请
CAMERA
权限,还要申请WRITE_EXTERNAL_STORAGE
权限。
- 在Android 7.0(及以上)手机开启拍照功能,既要申请
- Android 7.0(API24)以及以上版本不支持file://这种类型的URI,而是使用content://这种类型的URI。不然会报
android.os.FileUriExposedException
这个错,使用Android 7.0(及以上)手机拍照功能时,一定要注意这个api的变化。
- Android 7.0(API24)以及以上版本不支持file://这种类型的URI,而是使用content://这种类型的URI。不然会报
- 使用Android 8.0(及以上)手机更新安装apk时,在Mainfest.xml 中请求安装权限
android.permission.REQUEST_INSTALL_PACKAGES
。
- 使用Android 8.0(及以上)手机更新安装apk时,在Mainfest.xml 中请求安装权限
6、华为手机app闪退重启清空log日志问题
解决方案:
◆ 方式1(最全面的解决方案):
找到手机设置 ---> 最后的开发人员选项 ---> 在调试模块,打开USB调试。
还是调试模块内,找到日志记录器缓冲区大小,改为1M(也可选择更大),
然后进入拨号界面输入:*#*#2846579#*#* ----> 选择USB端口设置 ----> 选择Google模式。
◆ 方式2:拨号键盘 + 快捷键设置(这种方式不是所有log都能显示)
进入拨号界面输入:*#*#2846579#*#*
依次选择:后台设置 ---> LOG设置 ---> AP 日志,重新启动手机。
◆ 方式3:错误出现后,迅速拔掉USB线,这是一个拼手速的方法,成功率不敢保证。
7、关于华为手机App权限更改导致应用重启的坑(暂且我还没有很好的解决方式)
问题重现:
- 1.当我们在华为手机上打开一个应用,将应用退至后台进程中。
- 2.打开 “设置”去更改该应用的权限(比如将“存储”权限由授权状态改为非授权状态)。
- 3.再将该应用重新切换到前台,会发现应用进行了重新启动。 (在该app中,启动的时候,FragmentManager仍然会持有原有的fragment。)
网上有人说出了一种原因和一种 解决方案:当应用的权限发生变化的时候,华为手机发出广播,导致应用重新启动。 解决办法(比较笨):在Activity的onCreate()方法中,根据FragmentManager获取到已经存在的fragment,并将它们移除掉。重新再创建一下需要展示的fragment
但是我想知道framework层是如何操作的?不知道有没有大佬能够分析一下源码?
(三)魅族
魅族开发者文档
(四)锤子
锤子开发者文档
(五)oppo
1、oppo开发者文档
2、关于开发者选项
:
oppo手机的开发者模式很恶心,开启“设置”》其他设置》开发者选项》USB调试 待机,然后状态栏有个黄色的提醒窗口,提示10分钟后自动关闭开发者选项。
3、关于验证码
:
装个应用要验证码,打开开发者选项需要验证码。。很恶心。。
4、oppo手机的R9系列和A系列的5.1系统存在严重的bug,类似以下这种的gc导致的释放超时很多。
(六)vivo
vivo开发者文档
- 关于as项目无法在vivo中安装的问题:
最近适配vivo手机 用的是vivo x9 发现应用无法在手机上安装 已经打开了开发者模式还是不行,报以下错:
【解决方案】
关掉Android Studio的Instant Run功能,然后把开发者模式中的USB安全模式(在USB调试下面)和USB调试一起打开。(其他手机遇到同样问题,也可以用这个方式解决。)
二、开发中遇到的问题在不同手机上的处理方式
(一)沉浸式状态栏适配
- 这里讲一下华为手机沉浸式状态栏和虚拟键盘冲突问题怎么解决:
由于指数限制,详细代码请看我的github https://github.com/AweiLoveAndroid/Solve-StatusBar-VirtualKeyBoard
(二)沉浸式状态栏图标的适配
- 2.2.1 小米MIUI系统适配
之前做沉浸式状态栏,由于公司APP底色是白色,所以对MIUI进行特殊处理。在MIUI V6及以上版本,调用MIUI的方法将状态栏图标改为黑色。发现部分小米手机,这样的设置不管用,导致头上一片白,状态栏上的东西基本看不到。
调整过程中发现以下情况:
手机型号 | MIUI版本 | Android版本 | 系统方法是否生效 | MIUI的方法是否生效 |
---|---|---|---|---|
红米 NOTE 1LTE | MIUI 8 8.2.1稳定版 | 4.4 | 否 | 生效 |
小米5 | MIUI 8 8.5.3稳定版 | 7.0 | 否 | 生效 |
MI 3W | MIUI 9 7.9.14开发版 | 6.0.1 | 生效 | 否 |
参考官方文档: http://www.miui.com/thread-8946673-1-1.html
(三)应用卸载然后安装更新的适配
2.3.1 华为适配
华为手机程序卸载,安装更新包,还是提醒更新包与安装应用签名不一致。2.3.2 魅族适配
- 问题1. 测试的签名和你正式出包的签名如果不一致就不能安装,卸载应用也没用。
- 问题2. 用as安装过应用,卸载后安装正式的apk就安装不了,用adb命令卸载后就行了。
(四)改变状态栏字体颜色为黑色的适配
- 2.4.1 小米适配
/**
* 改变小米的状态栏字体颜色为黑色,要求MIUI6以上
* tested on: MIUI V7 5.0 Redmi-Note3
*/
private void processMIUI(boolean lightStatusBar) throws Exception{
Window window = getWindow();
Class<? extends Window> clazz = window.getClass();
int darkModeFlag;
Class<?> layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
darkModeFlag = field.getInt(layoutParams);
Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
extraFlagField.invoke(window,lightStatusBar ? darkModeFlag : 0, darkModeFlag);
}
- 2.4.2 魅族适配
/**
* 改变魅族的状态栏字体为黑色,要求FlyMe4以上
*/
private void processFlyMe(boolean isLightStatusBar) throws Exception{
Window window = getWindow();
WindowManager.LayoutParams layoutParams = window.getAttributes();
Class<?> instance = Class.forName("android.view.MiuiWindowManager$LayoutParams");
int value = instance.getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON").getInt(layoutParams);
Field field = instance.getDeclaredField("meizuFlags");
field.setAccessible(true);
int origin = field.getInt(layoutParams);
if(isLightStatusBar){
field.set(layoutParams, origin | value);
}else{
field.set(layoutParams, -value | origin);
}
}
下面来一张示例图:
(五)屏幕圆角实现和适配
- 实现原理:利用WindowManager将我们的圆角加到屏幕的四个角,圆角颜色设置为黑色,形成视觉圆角屏幕。
下面简单的把一些核心代码讲一下:
- ** 自定义圆角View,这里以左上角为例:**
// top left
case Gravity.TOP | Gravity.LEFT:
path.moveTo(0.0f, 0.0f);
path.lineTo(0.0f, (float) h);
path.arcTo(new RectF(0.0f, 0.0f,
((float) w) * 2.0f, ((float) h) * 2.0f), 180.0f, 90.0f, true);
path.lineTo((float) w, 0.0f);
path.lineTo(0.0f, 0.0f);
path.close();
break;
- windowmanager在添加view的时候需要设置一个WindowManager.LayoutParams。下面初始化这个Params:
// window manager
manager = (WindowManager) this.getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
params = new WindowManager.LayoutParams();
/*
系统提示类型:7.0以前可以直接用TOAST的类型,不用申请权限,直接添加
7.0以后不行了,需要申请SYSTEM_ALERT_WINDOW权限,window type最好
设置为ERROR 或者 PHONE
*/
if (Utilities.isCanUseToastType()) {
params.type = WindowManager.LayoutParams.TYPE_TOAST;
} else {
params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
}
params.format = 1;
params.flags = WindowManager.LayoutParams.FLAG_FULLSCREEN // 全屏
| WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS // 覆盖到status bar
| WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION // 覆盖到导航栏
// 以下属性设置加载我们圆角window 不抢焦点,不拦截事件
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
params.alpha = 1.0f;
params.x = 0;
params.y = 0;
// 设置 大小为全屏
params.width = ViewUtil.getScreenSize(this).x;
params.height = ViewUtil.getScreenSize(this).y;
- 圆角加到屏幕上:
public void addCornerViewByPosition(String position){
boolean enable = true;
switch (position) {
case LEFT_TOP:
enable = leftTopEnable;
params.gravity = Gravity.TOP | Gravity.LEFT;
break;
case RIGHT_TOP:
enable = rightTopEnable;
params.gravity = Gravity.TOP | Gravity.RIGHT;
break;
case LEFT_BOTTOM:
enable = leftBottomEnable;
params.gravity = Gravity.BOTTOM | Gravity.LEFT;
break;
case RIGHT_BOTTOM:
enable = rightBottomEnable;
params.gravity = Gravity.BOTTOM | Gravity.RIGHT;
break;
}
CornerView corner = buildCorner(enable,params.gravity);
if(!corners.containsValue(corner)) {
corners.put(position, corner);
manager.addView(corner, params);
}
}
屏幕圆角实现和适配,详细的可以点击这里:http://mp.weixin.qq.com/s/h5qRvfgVj04f_xExTtrIHg
(六)在带虚拟按键的手机上,虚拟按键会遮挡全屏图片的底部的解决。
在做splash页面的时候,通过windowBackground设置背景图片,在带虚拟按键的手机上,虚拟按键会遮挡图片的底部,这个问题的解决方式:
参考:http://blog.csdn.net/c15522627353/article/details/52452490
究竟如何适配Android底部虚拟按键,可以参考这篇博文:https://www.jianshu.com/p/b499628e0ae0
(七)悬浮窗权限设置了,dialog还是不提示。
(八)在Nexus 手机,原生Android 8.0上,使用扫码的时候显示的拍照预览方向不正,有180度的旋转并且变形的,解决方案:
private void surfaceIsChanged() {
if (mHolder.getSurface() == null) {
System.out.println("getSurface,nullnull");
return;
}
try {
mCamera.stopPreview();
} catch (Exception e) {
e.printStackTrace();
}
try {
Camera.Size previewSize = mCamera.getParameters().getPreviewSize();
int dataBufferSize = (int) (previewSize.height * previewSize.width
* (ImageFormat.getBitsPerPixel(mCamera.getParameters()
.getPreviewFormat()) / 8.0));
mCamera.addCallbackBuffer(new byte[dataBufferSize]);
mCamera.addCallbackBuffer(new byte[dataBufferSize]);
mCamera.addCallbackBuffer(new byte[dataBufferSize]);
mCamera.setPreviewDisplay(mHolder);
mCamera.setPreviewCallback(previewCallback);
mCamera.startPreview();
mCamera.autoFocus(autoFocusCallback);
// 核心代码:根据照相的内容进行设置显示方向。
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
// DO your logic to get front or back camera...or loop through all avaialable.
int camIdx = 0;
Camera.getCameraInfo(camIdx, cameraInfo);
try {
// If using back camera then simply rotate what CameraInfo tells you.
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK){
mCamera.setDisplayOrientation(cameraInfo.orientation);
}else{
// If using front camera note that image might be flipped
// to give users the impresion the are looking at a mirror.
mCamera.setDisplayOrientation( (360 - cameraInfo.orientation) % 360);
}
} catch (Exception e) {
e.printStackTrace();
}
//开始扫描
// Toast.makeText(QRZbarActivity.this, "开始扫描",Toast.LENGTH_SHORT).show();
// 打开闪光灯,这个方法自己去实现,这里不是重点,就不写了。
autoOpenLight();
} catch (Exception e) {
Toast.makeText(BaseScanActivity.this, R.string.account_toast_not_open_camera,
Toast.LENGTH_SHORT).show();
// showTip("您未允许" + getResources().getString(R.string.app_name)
// + "访问您的相册\n请在“安全中心 -授权管理”中更改设置");
Log.d("DBG", "Error starting camera preview: " + e.getMessage());
}
}
(九)获取手机里所有存储设备盘符,不同厂商手机的路径可能不一样。
问题描述:华为手机很变态,存储路径跟原生系统的不一样,所以需要对其做特别处理。
解决方案:需要用到一个被系统隐藏的方法,即StorageManager下的getVolumePaths()方法。具体通过反射可以得到,其中mPath、mRemovable、mEmulated、mState这几个属性是我们需要关注的。
作者:AWeiLoveAndroid
链接:https://www.jianshu.com/p/f9c67a4b908e
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
Android ROM适配的更多相关文章
- 腾讯优测-优社区干货精选 | 那些年,我们在Android机型适配上遇到的坑之Camera拍照时快门咔嚓声
文/腾讯优测研发工程师 吴宇焕 优测小优有话说: android机型适配的坑自然是不少,不想掉坑快来优测优社区~ 现在Android手机一般都会带有照相功能,有很多朋友就发现手机照相时快门声音很响,想 ...
- Android屏幕适配全攻略 (转载)
http://blog.csdn.net/jdsjlzx/article/details/45891551 https://github.com/hongyangAndroid/AndroidAuto ...
- 【收藏】Android屏幕适配全攻略(最权威的Google官方适配指导)
来源:http://blog.csdn.net/zhaokaiqiang1992 更多:Android AutoLayout全新的适配方式, 堪称适配终结者 Android的屏幕适配一直以来都在折磨着 ...
- Android屏幕适配全攻略(最权威的官方适配指导)(转),共大家分享。
Android的屏幕适配一直以来都在折磨着我们这些开发者,本篇文章以Google的官方文档为基础,全面而深入的讲解了Android屏幕适配的原因.重要概念.解决方案及最佳实践,我相信如果你能认真的学习 ...
- Android屏幕适配dp、px两套解决办法
"又是屏幕适配,这类文章网上不是很多了吗?" 我也很遗憾,确实又是老问题.但本文重点对网上的各种方案做一个简短的总结,和具体使用方法. 若想了解具体Android设备适配的前世因果 ...
- Android屏幕适配全攻略(最权威的官方适配指导) (转)
招聘信息: Cocos2d-X 前端主程 [新浪微博]手机客户端iOS研发工程师 20k-40k iOS 开发工程师 iOS高级开发工程师(中国排名第一的企业级移动互联网云计算公司 和创科技 红圈营销 ...
- Android Material适配 为控件设置指定背景色和点击波纹效果
Android Material适配 为控件设置指定背景色和点击波纹效果,有需要的朋友可以参考下. 大部分时候,我们都需要为控件设置指定背景色和点击效果 4.x以下可以使用selector,5.0以上 ...
- 腾讯优测| 让Android屏幕适配开发更简单-Google百分比布
文/腾讯优测工程师 吴宇焕 腾讯优测优社区干货精选~ 相信开发同学都被安卓设备碎片化的问题折磨过,市面上安卓手机的主流屏幕尺寸种类繁多,给适配造成很大的困难.就算搞定了屏幕尺寸问题,各种分辨率又让人眼 ...
- Android分辨率适配心得
关于Android分辨率适配,这个是Android开发很头疼的一个问题,也需要花费相当一部分开发时间处理的一个问题,往往一个界面怎么适配就得想半天,特别是新手,也经常有人问我是怎么适配分辨率的,我也不 ...
随机推荐
- 内核开机logo
安装 # sudo apt-getinstall netpbm 制图 # bmptoppm logo.bmp > logo.ppm # ppmquant 224 logo.ppm > lo ...
- Spring web.xml详解
web.xml文件是Java Web项目中的一个配置文件,主要用于配置欢迎页.Filter.Listener.Servlet等,但并不是必须的,一个Java Web项目没有web.xml文件也是照样能 ...
- shell菜单选择
我们会遇到很多进入后台系统的时候,会根据选择,进入不同的系统,下面是一个简单的例子: #!/bin/sh function menu (){ cat << EOF------------- ...
- Swift Review总结一:从 Swift Style 开始
最近凑了几个热心的小伙伴写一些Swift的新手demo(两周后应该能和大家见面了),我参与了review.于是借demo里的代码总结一下新手写Swift要注意的问题,尤其是从oc转到用swift写的开 ...
- [USACO19JAN]Redistricting——单调队列优化DP
原题链接 首先有一个\(O(nk)\)的很显然的\(dp\),把荷斯坦牛看成\(1\),把更赛牛看成\(-1\),这样就可以很方便地通过前缀和来判断某一段中谁有优势了 考虑怎么优化,观察转移: \[f ...
- 多种view视图和序列化--django2
models.py from django.db import models # Create your models here. class Idc(models.Model): name = mo ...
- mybayis项目使用的Mapping文件使用总结参考(二)
针对in字句中的数组使用方法 <select id="getCpProfileNamesByIds" resultType="string"> se ...
- 牛客寒假算法基础集训营2 【处女座与复读机】DP最小编辑距离【模板题】
链接:https://ac.nowcoder.com/acm/contest/327/G来源:牛客网 一天,处女座在牛客算法群里发了一句“我好强啊”,引起无数的复读,可是处女座发现复读之后变成了“处女 ...
- Luogu P5018 对称二叉树 瞎搞树&哈希
我的天..普及组这么$hard$... 然后好像没有人用我的垃圾做法,,,好像是$O(n)$,但十分的慢,并且极其暴力$qwq$ 具体来说,就是直接$dfs$求出树高,然后想像出把原来的树补成满二叉树 ...
- TTTTTTTTTTTTTTTT hdu 5727 Necklace 阴阳珠 二分图匹配+暴力全排列
Necklace Time Limit: 3000/1500 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Su ...