Android 开发中遇到的 bug(3)

1 安装 apk 时 INSTALL_FAILED_ALREADY_EXISTS

E:\wangzhichao_dir\fusoft\apk>adb install E:\wangzhichao_dir\fusoft\apk\google-play-8-3-73-u-all-0-fp-173262113.apk
adb: failed to install E:\wangzhichao_dir\fusoft\apk\google-play-8-3-73-u-all-0-fp-173262113.apk: Failure [INSTALL_FAILED_VERSION_DOWNGRADE]

E:\wangzhichao_dir\fusoft\apk>adb uninstall com.android.vending
Success

E:\wangzhichao_dir\fusoft\apk>adb install E:\wangzhichao_dir\fusoft\apk\google-play-8-3-73-u-all-0-fp-173262113.apk
adb: failed to install E:\wangzhichao_dir\fusoft\apk\google-play-8-3-73-u-all-0-fp-173262113.apk: Failure [INSTALL_FAILED_ALREADY_EXISTS: Attempt to re-install
com.android.vending without first uninstalling.]

E:\wangzhichao_dir\fusoft\apk>adb uninstall com.android.vending
Failure [DELETE_FAILED_INTERNAL_ERROR]

E:\wangzhichao_dir\fusoft\apk>adb uninstall com.android.vending
Failure [DELETE_FAILED_INTERNAL_ERROR]

E:\wangzhichao_dir\fusoft\apk>adb install -r E:\wangzhichao_dir\fusoft\apk\google-play-8-3-73-u-all-0-fp-173262113.apk
error: no devices/emulators found
adb: error: failed to get feature set: no devices/emulators found
- waiting for device -

E:\wangzhichao_dir\fusoft\apk>adb install -r E:\wangzhichao_dir\fusoft\apk\google-play-8-3-73-u-all-0-fp-173262113.apk
Success

时间:2019年1月31日15:37:16
解决办法:可以看上面的命令,主要是使用了 adb install -r 命令。在这当中,还重启了一次手机。

2 getExternalFilesDir 返回 null

Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.io.File.getPath()' on a null object reference

下面这段代码,在友盟统计上上报了异常:

public static String getFileDir(String folder) {
    Context context = MyApplication.getContext();
    String cachePath = null;
    if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())
            || !Environment.isExternalStorageRemovable()) {
        cachePath = context.getExternalFilesDir(folder).getPath();
    } else {
        cachePath = context.getFilesDir().getPath() + File.separator + folder;
    }
    return cachePath;
}

时间:2019年1月31日16:47:13
解决办法:if 分支里的 || 应该写为 &&,因为在存储卡没有 MEDIA_MOUNTED 但也没有移除时,会进入 if 分支,这种情况下 context.getExternalFilesDir(folder) 会返回 null
另外,即便存储卡已经是 MEDIA_MOUNTED 状态,context.getExternalFilesDir(folder) 也可能返回 null,造成异常(参考:https://stackoverflow.com/questions/27463407/getexternalfilesdirnull-returns-null-for-some-users )。所以,需要对 context.getExternalFilesDir(folder) 做非空校验。
修改后的代码如下:

public static String getFileDir(String folder) {
    Context context = MyApplication.getContext();
    String cachePath;
    if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())
            && !Environment.isExternalStorageRemovable()
            && (context.getExternalFilesDir(folder) != null)) {
            cachePath = context.getExternalFilesDir(folder).getPath();
    } else {
        cachePath = context.getFilesDir().getPath() + File.separator + folder;
    }
    File file = new File(cachePath);
    if (!file.isDirectory()) {
        boolean mkdirs = file.mkdirs();
        LogUtils.d("getFileDir: mkdirs="+mkdirs);
    }
    return cachePath;

3 Manifest merger failed

错误日志如下:

Manifest merger failed : Attribute application@appComponentFactory value=(android.support.v4.app.CoreComponentFactory) from [com.android.support:support-compat:28.0.0] AndroidManifest.xml:22:18-91
	is also present at [androidx.core:core:1.0.0] AndroidManifest.xml:22:18-86 value=(androidx.core.app.CoreComponentFactory).
	Suggestion: add 'tools:replace="android:appComponentFactory"' to <application> element at AndroidManifest.xml:11:5-36:19 to override.

从错误日志可以看到,appComponentFactory 在 com.android.support:support-compat:28.0.0 里存在,也在 androidx.core:core:1.0.0 里存在,导致合并失败。可以我没有去引用 androidx.core:core:1.0.0。查看我的 External libraries,确实看到了 androidx.core:core:1.0.0 的一大堆引用。它们是怎么进来的呢?
在 Terminal 里输入命令:

gradlew :app:dependencies

看到了:

是因为引用了这个第三方库才有了 androidx 的库。
修改依赖方式,移除不需要的 group:

implementation ("org.permissionsdispatcher:permissionsdispatcher:$rootProject.permissionsdispatcher_version"){
        exclude group: 'androidx.core'
        exclude group: 'androidx.fragment'
        exclude group: 'androidx.collection'
}

4 错误: 程序包androidx.databinding不存在

时间:2019年2月18日21:16:43
解决办法:在 gradle.properties 文件中添加

android.useAndroidX=true

当设置为true时,Android 插件使用合适的AndroidX库而非一个Support库。

5 Error: Program type already present: android.support.v4.app.INotificationSideChannel

时间:2019年2月18日21:23:05
解决办法:在 gradle.properties 文件中添加

android.enableJetifier=true

参考官方文档 Using AndroidX

android.enableJetifier: When set to true, the Android plugin automatically migrates existing third-party libraries to use AndroidX by rewriting their binaries. The flag is false by default if it is not specified.

6 Caused by: java.lang.IllegalStateException: This Activity already has an action bar supplied by the window decor. Do not request Window.FEATURE_SUPPORT_ACTION_BAR and set windowActionBar to false in your theme to use a Toolbar instead.

时间:2019年2月21日14:08:43
解决办法:修改 Activity 的 theme 为

<style name="AppTheme.NoActionBar">
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
</style>

7 使用 Databinding 却无法引用到 include 标签内的控件

时间:2019年2月21日14:12:21
解决办法:

  1. <include> 标签引用的布局转成 Databinding 需要的 layout 节点的布局,如 databinding_include_textview.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>

    </data>

    <TextView
        android:id="@+id/tv"
        android:layout_width="100dp"
        android:background="#44ff0000"
        android:text="I am an include textview."
        android:layout_height="100dp"/>
</layout>
  1. <include> 标签所在的布局转成 Databinding 需要的 layout 节点的布局。
    在代码中获取对应控件的方式,如 activity_databinding_include.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>

    </data>

    <android.support.constraint.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <include
            layout="@layout/databinding_include_textview"/>

    </android.support.constraint.ConstraintLayout>
</layout>
  1. <include> 标签添加 id:
<include
            android:id="@+id/include_textview"
            layout="@layout/databinding_include_textview"/>
  1. 在代码中获取 TextView 的方式:
ActivityDatabindingIncludeBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_databinding_include);
        binding.includeTextview.tv.setText("Study hard.");

8 错误: 找不到符号 符号: 类 AppManagerActivityBindingImpl 位置: 程序包 com.bat.clean.databinding

时间:2019年2月26日11:05:26
解决办法:查看 Run tasks 下报错的 :app:compileDebugJavaWithJavac 这个任务,显示出来的日志:

java.lang.RuntimeException: android.databinding.tool.util.LoggedErrorException: Found data binding errors.
****/ data binding error ****msg:Could not find accessor android.view.View.VISBLE
file:E:\AndroidWorkspaces\BatCleaner\app\src\main\res\layout\app_manager_activity.xml
loc:66:64 - 66:74

可以看到这句:

Could not find accessor android.view.View.VISBLE

原来是自己把 View.VISIBLE 写成了 View.VISBLE。

<ProgressBar
                android:id="@+id/pb"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:visibility="@{viewmodel.mShowProgress ? View.VISBLE: View.GONE}"/>

改为

<ProgressBar
                android:id="@+id/pb"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:visibility="@{viewmodel.mShowProgress ? View.VISIBLE: View.GONE}"/>

改过来,重新运行,ok 了。学习到的一点是一定要认真查看日志,大多数情况下日志中都已经包含了出错的地方;有时候还会给出建议的解决办法。

9 API 19 手机上出现 java.lang.RuntimeException: Unable to get provider com.google.firebase.provider.FirebaseInitProvider: java.lang.ClassNotFoundException: Didn’t find class “com.google.firebase.provider.FirebaseInitProvider” on path

错误日志如下:

java.lang.RuntimeException: Unable to get provider com.google.firebase.provider.FirebaseInitProvider: java.lang.ClassNotFoundException: Didn't find class "com.google.firebase.provider.FirebaseInitProvider" on path: DexPathList[[zip file "/data/app/com.bat.clean-1.apk"],nativeLibraryDirectories=[/data/app-lib/com.bat.clean-1, /vendor/lib, /system/lib]]
        at android.app.ActivityThread.installProvider(ActivityThread.java:5018)
        at android.app.ActivityThread.installContentProviders(ActivityThread.java:4589)
        at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4522)
        at android.app.ActivityThread.access$1500(ActivityThread.java:151)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1381)
        at android.os.Handler.dispatchMessage(Handler.java:110)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:5299)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:515)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:825)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:641)
        at dalvik.system.NativeStart.main(Native Method)
     Caused by: java.lang.ClassNotFoundException: Didn't find class "com.google.firebase.provider.FirebaseInitProvider" on path: DexPathList[[zip file "/data/app/com.bat.clean-1.apk"],nativeLibraryDirectories=[/data/app-lib/com.bat.clean-1, /vendor/lib, /system/lib]]
        at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:497)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:457)
        at android.app.ActivityThread.installProvider(ActivityThread.java:5003)
        at android.app.ActivityThread.installContentProviders(ActivityThread.java:4589) 
        at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4522) 
        at android.app.ActivityThread.access$1500(ActivityThread.java:151) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1381) 
        at android.os.Handler.dispatchMessage(Handler.java:110) 
        at android.os.Looper.loop(Looper.java:193) 
        at android.app.ActivityThread.main(ActivityThread.java:5299) 
        at java.lang.reflect.Method.invokeNative(Native Method) 
        at java.lang.reflect.Method.invoke(Method.java:515) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:825) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:641) 
        at dalvik.system.NativeStart.main(Native Method) 

时间:2019年2月28日15:39:38
解决办法:

  1. 添加 multidex 依赖:
dependencies {
  implementation 'com.android.support:multidex:1.0.3'
}
  1. 在主 module 的 gradle 文件中添加:
 defaultConfig {
        ...
        multiDexEnabled true
    }
  1. 在自定义的 Application 类中添加:
@Override
protected void attachBaseContext(Context base) {
    super.attachBaseContext(base);
    MultiDex.install(this);
}

参考 https://stackoverflow.com/questions/39825543/didnt-find-class-com-google-firebase-provider-firebaseinitprovider

10 NestedScrollView 嵌套 RecyclerView,列表向下滚动的问题

问题描述:在 NestedScrollView 里嵌套 RecyclerView,加载完数据后,发现列表已经向下滚动了。
时间:2019年2月28日21:32:16
解决办法:
设置

 // 避免 recyclerview 刚打开页面就向下滚动
 recyclerview .setFocusable(false);

参考 https://www.jianshu.com/p/3e710a5ee50b
另外发现,在 NestedScrollView 中嵌套 RecyclerView 后,RecyclerViewAdapter 中的回调在加载完数据后,即便再滚动列表也不会重新走 onCreateViewHolderonBindViewHolder 的回调了。这个问题,还不知道原因。

发布了78 篇原创文章 · 获赞 46 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/willway_wang/article/details/86715680
今日推荐