平时csdn看资料的时候,都是游客模式,前两天要看个评论,不得不登一下,发现之前写的一个心得,有好几个朋友评论了。虽然是很小的问题,但能帮到别人,心里就很满足2333
正好近期把targetSdkVersion 升到了28,适配过程中踩到了各种坑,趁此机会写一篇个人总结与诸位一起分享。
1. 腾讯云-语音识别 code=-301 & 7.0无法抓包 & MTA崩溃
这几个其实本质是一个问题。详情参考官方文档网络安全配置。可以看到关键的一点是“从 Android 9(API 级别 28)开始,系统默认情况下已停用明文支持。”,即 cleartextTrafficPermitted="false"。
由此而知,腾讯云语音识别一直报错code=-301, message=server connect failed,其实是因为加了这个设置ClientConfiguration.setServerProtocolHttps(false); 导致接口都是http,自然无法使用了,去掉该配置就可以了,因为默认是用的https。因为demo中是这么设置的,所以之前同事就copy过来了,我升级target sdk后发现不能用也没多想就给腾讯云提了工单,那边一开始也接锅表示会修复的,结果升新版后还是不行,一来一回花了不少时间,以后用sdk还是得多看文档,但这语音识别的文档也太简陋了,连版本日志都没...
MTA崩溃也是同样的问题,一上报就崩了,CLEARTEXT communication to xxx not permitted by network security policy,看了下MTA已经是新版本了,再加上其他sdk中可能还有http的,所以索性修改networkSecurityConfig,允许明文。
7.0以上不能抓包则同样需要在networkSecurityConfig中配置信任的证书,我选择了debug调试时信任所有证书。
networkSecurityConfig配置如下:
在res/xml中新建 network_security_config.xml
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<debug-overrides cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
<certificates src="user" />
</trust-anchors>
</debug-overrides>
<base-config cleartextTrafficPermitted="true" />
</network-security-config>
在AndroidManifest里的<application>标签中,添加代码:
android:networkSecurityConfig="@xml/network_security_config"
以上问题就一并解决啦,各位可以根据自己的需求来进行配置。
2. java.lang.IllegalStateException: Only fullscreen opaque activities can request orientation
这个问题发生在android 8.0 的机子上,app都没进就崩了,我的心也跟着一起崩了啊23333
在这个问题中有较多讨论,问题来源是源码中这一段
//Need to pay attention mActivityInfo.isFixedOrientation() and ActivityInfo.isTranslucentOrFloating(ta)
if (getApplicationInfo().targetSdkVersion >= O_MR1 && mActivityInfo.isFixedOrientation()) {
final TypedArray ta = obtainStyledAttributes(com.android.internal.R.styleable.Window);
final boolean isTranslucentOrFloating = ActivityInfo.isTranslucentOrFloating(ta);
ta.recycle();
//Exception occurred
if (isTranslucentOrFloating) {
throw new IllegalStateException(
"Only fullscreen opaque activities can request orientation");
}
}
解决方法:项目中很多activity用的主题都是透明的
<style name="CommonTheme" parent="AppTheme">
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">@color/white</item>
</style>
将用到透明主题的acitivity在manifest中的
android:screenOrientation="portrait"
这行都去掉就可以了,经测试,如果透明activity后面有不透明的固定方向的activity,透明的是不会转动的,所以主页activity不要用透明主题就好。
3. android 9.0 pie windowSoftInputMode不管怎么设置 进入activity键盘不会自动弹出
这个问题也蛮妖的,就是在9.0上弹不出键盘,android:windowSoftInputMode="adjustResize|stateVisible"不起作用。
依旧是在stackoverflow找到了解决办法,在9.0上,没有自动获取焦点,那就只能手动代码中requestFocus,或者xml加上</requestFocus>,例如:
<EditText
android:id="@+id/et_envelope_post_script"
android:layout_width="match_parent"
android:layout_height="98dp"
android:background="@color/white"
android:gravity="left|top"
android:padding="16dp"
android:textSize="16sp">
<requestFocus />
</EditText>
4. okhttp3 通过multipart上传文件名为中文报错Caused by: java.lang.IllegalArgumentException: Unexpected char
顺便升级了一下okhttp3,结果bugly中几个上报都是通过multipart/form-data上传书封时的,是因为用到的本地图片文件名含中文,报错如下:
Caused by: java.lang.IllegalArgumentException: Unexpected char 0x6211 at 39 in Content-Disposition value: form-data; name="bookCover"; filename="我推荐吗.jpg"
代码使用:
MultipartBody.Builder builder = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart(param, targetFile.getName(), RequestBody.create(MEDIA_TYPE, targetFile));
源码部分:
/** Add a form data part to the body. */
public Builder addFormDataPart(String name, @Nullable String filename, RequestBody body) {
return addPart(Part.createFormData(name, filename, body));
}
public static Part createFormData(String name, @Nullable String filename, RequestBody body) {
if (name == null) {
throw new NullPointerException("name == null");
}
StringBuilder disposition = new StringBuilder("form-data; name=");
appendQuotedString(disposition, name);
if (filename != null) {
disposition.append("; filename=");
appendQuotedString(disposition, filename);
}
return create(Headers.of("Content-Disposition", disposition.toString()), body);
}
public static Headers of(String... namesAndValues) {
if (namesAndValues == null) throw new NullPointerException("namesAndValues == null");
if (namesAndValues.length % 2 != 0) {
throw new IllegalArgumentException("Expected alternating header names and values");
}
// Make a defensive copy and clean it up.
namesAndValues = namesAndValues.clone();
for (int i = 0; i < namesAndValues.length; i++) {
if (namesAndValues[i] == null) throw new IllegalArgumentException("Headers cannot be null");
namesAndValues[i] = namesAndValues[i].trim();
}
// Check for malformed headers.
for (int i = 0; i < namesAndValues.length; i += 2) {
String name = namesAndValues[i];
String value = namesAndValues[i + 1];
checkName(name);
checkValue(value, name);
}
return new Headers(namesAndValues);
}
static void checkName(String name) {
if (name == null) throw new NullPointerException("name == null");
if (name.isEmpty()) throw new IllegalArgumentException("name is empty");
for (int i = 0, length = name.length(); i < length; i++) {
char c = name.charAt(i);
if (c <= '\u0020' || c >= '\u007f') {
throw new IllegalArgumentException(Util.format(
"Unexpected char %#04x at %d in header name: %s", (int) c, i, name));
}
}
}
static void checkValue(String value, String name) {
if (value == null) throw new NullPointerException("value for name " + name + " == null");
for (int i = 0, length = value.length(); i < length; i++) {
char c = value.charAt(i);
if ((c <= '\u001f' && c != '\t') || c >= '\u007f') {
throw new IllegalArgumentException(Util.format(
"Unexpected char %#04x at %d in %s value: %s", (int) c, i, name, value));
}
}
}
由此可知,文件名中含中文时,checkValue会抛出异常,解决办法就是上传前重命名文件名。同时注意,header头中也是不能带中文的。
5. 其他
有些项目中已经适配,或者没涉及的点,也一起提一下。
一个是7.0开始App对外无法暴露file://类型的URI了,在类似调用系统相机或是通过代码安装apk等需要暴露uri给其他app的情况下,会抛出FileUriExposedException异常,需要使用FileProvider来定义对外暴露的文件夹路径,再调用:
FileProvider.getUriForFile(this.mContext.getApplicationContext(), authority, file);
来获取content://类型的Uri。其中authority指在manifest的<provider>中配置的provider名,例如:
<provider
android:name="me.iwf.photopicker.utils.PhotoFileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/__picker_provider_paths"/>
</provider>
其中__picker_provider_paths是在res/xml中定义的对外暴露的文件夹路径,如下:
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path name="external_storage_root" path="."/>
<files-path name="files" path="."/>
</paths>
关于paths配置比较详细的讲解可参考Android 7.0适配-应用之间共享文件(FileProvider)
二是android 8.0以上未知来源的应用是不可以通过代码来执行安装的,会提示“解析包时出现问题”。需要申明权限
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
并在代码中动态申请。 这么一想之前一些app更新时是碰到过这个问题,当时只当是apk有问题,现在看来是没有进行适配。我们的项目因为是直接跳到网页进行下载的,所以没有碰到这个问题。
目前为止碰到的问题大概就这些,如果之后还有的话,会在此更新的,也希望各位能留言自己在升级sdk中碰到的坑,我也会一并整理进来的。
本文详细介绍了在将Android应用的targetSdkVersion升级到28时遇到的各种问题及解决方案,包括腾讯云语音识别错误、7.0以上设备的抓包问题、MTA崩溃、全屏活动请求方向限制、Android 9.0键盘不自动弹出、okhttp3上传文件名中文报错等。并提供了解决这些问题的具体步骤和代码示例。
477

被折叠的 条评论
为什么被折叠?



