Android 问题记录和解决之道

443 阅读4分钟

2014/2/23

[问题] splashScreen.setOnExitAnimationListener() not called when using CustomSplashScreen in debug mode

google 论坛 对于该问题 的解释

image.png

所以当有时候安装包通过自己安装的,在某些设备上 安装成功后,提供了一个打开 app的 按钮,通过点击这种这个按钮 打开 app的方式;而不是直接点击app 启动Icon的方式来启动app,第一次启动时 就会存在setOnExitAnimationListener 的回调 不会执行;

[解决方案]


 private AtomicBoolean mShowDialogBoolean = new AtomicBoolean(false);
 
 
 mSplashScreen.setOnExitAnimationListener(new SplashScreen.OnExitAnimationListener() {
        @Override
        public void onSplashScreenExit(@NonNull SplashScreenViewProvider splashScreenViewProvider) {
            if (isFisrt) {
                //有时候不会执行该回调,通过下面的 getWindow().getDecorView().postDelayed()
                showPrivacyDialog(1);
                return;
            }
        }
    });

 getWindow().getDecorView().postDelayed(new Runnable(){
                    @Override
                    public void run() {
                         if (isFisrt) {
                            showPrivacyDialog();
                            }
                    }
                },2000);
                

private void  showPrivacyDialog(){

  if (mShowDialogBoolean.get()){
            return;
        }
    mShowDialogBoolean.compareAndSet(false, true);
    //....
}

2024/1/30

[问题] Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent. Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if some functionality depends on the PendingIntent being mutable, e.g. if it needs to be used with inline replies or bubbles.

Fatal Exception: java.lang.IllegalArgumentException: ****: Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.
Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if some functionality depends on the PendingIntent being mutable, e.g. if it needs to be used with inline replies or bubbles.
       at android.app.PendingIntent.checkFlags(PendingIntent.java:375)
       at android.app.PendingIntent.getActivityAsUser(PendingIntent.java:458)
       at android.app.PendingIntent.getActivity(PendingIntent.java:444)
       at android.app.PendingIntent.getActivity(PendingIntent.java:408)
       at com.google.android.gms.common.GoogleApiAvailabilityLight.getErrorResolutionPendingIntent(GoogleApiAvailabilityLight.java:3)
       at com.google.android.gms.common.GoogleApiAvailabilityLight.getErrorResolutionPendingIntent(GoogleApiAvailabilityLight.java:1)
       at com.google.android.gms.common.GoogleApiAvailability.getErrorResolutionPendingIntent(GoogleApiAvailability.java:1)
       at com.google.android.gms.common.GoogleApiAvailability.getErrorResolutionPendingIntent(GoogleApiAvailability.java:4)
       at com.google.android.gms.common.GoogleApiAvailability.zac(GoogleApiAvailability.java:1)
       at com.google.android.gms.common.api.internal.GoogleApiManager.zap(GoogleApiManager.java:1)
       at com.google.android.gms.common.api.internal.zabl.zac(zabl.java:21)
       at com.google.android.gms.common.api.internal.zabl.zam(zabl.java:7)
       at com.google.android.gms.common.api.internal.zabl.zad(zabl.java:8)
       at com.google.android.gms.common.api.internal.GoogleApiManager.handleMessage(GoogleApiManager.java:64)
       at android.os.Handler.dispatchMessage(Handler.java:102)
       at android.os.Looper.loopOnce(Looper.java:210)
       at android.os.Looper.loop(Looper.java:299)
       at android.os.HandlerThread.run(HandlerThread.java:67)

[分析]

Android 项目 升级到 31 之后,使用PendingIntent需要指定FLAG_IMMUTABLE或FLAG_MUTABLE标志。一般为了解决这个问题,你需要在创建PendingIntent时添加这两个标志之一;但是这里报错的地方是 com.google.android.gms.common.GoogleApiAvailabilityLight 类里面的方法 报出错误,应该是项目引用的 版本太旧,没有处理 31以后的兼容性,所以需要 把对应的 依赖库版本 更改较新版本;

implementation 'com.google.android.gms:play-services-base:18.2.0'

但在项目和组件库中找了一遍,并没有发现有依赖这个库,这里有奇怪,加上上面的依赖后 解决了该问题;

2023/11/22

[问题]

Caused by: java.lang.IllegalStateException: Only fullscreen opaque activities can request orientation
at android.app.Activity.onCreate(Activity.java:1038)
at android.support.v4.app.SupportActivity.onCreate(ComponentActivity.java:75)
at android.support.v4.app.FragmentActivity.onCreate(FragmentActivity.java:335)
at android.support.v7.app.AppCompatActivity.onCreate(AppCompatActivity.java:85)

[分析]

源码:

protected void onCreate(@Nullable Bundle savedInstanceState) {  
        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();  
            if (isTranslucentOrFloating) {  
                throw new IllegalStateException(  
                        "Only fullscreen opaque activities can request orientation");  
            }  
        }  
 }

当界面透明色或者悬浮,且设置屏幕方向的情况下,导致抛出异常

[解决]

绕过该检查,通过反射修改屏幕方向不固定,规避出错问题

override fun onCreate(savedInstanceState: Bundle?) {
    if (Build.VERSION.SDK_INT == Build.VERSION_CODES.O || Build.VERSION.SDK_INT == Build.VERSION_CODES.O_MR1) {
        var isTranslucentOrFloating = false
        try {
            val styleableRes = Class.forName("com.android.internal.R$styleable")
                .getField("Window")[null] as IntArray
            val typedArray = obtainStyledAttributes(styleableRes)
            val method: Method = ActivityInfo::class.java.getMethod("isTranslucentOrFloating", TypedArray::class.java)
            method.isAccessible = true
            val o =  method.invoke(null, typedArray)
            if (o != null){
                isTranslucentOrFloating = o as Boolean
            }
            method.isAccessible = false
        } catch (e:Exception) {
            e.printStackTrace()
        }

        if (isTranslucentOrFloating){
            try {
                val activityClass: Class<*> = Activity::class.java
                val mActivityInfoField: Field = activityClass.getDeclaredField("mActivityInfo")
                mActivityInfoField.isAccessible = true
                val activityInfo = mActivityInfoField.get(this) as ActivityInfo
                //设置屏幕不固定
                activityInfo.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
            } catch (e: java.lang.Exception) {
                e.printStackTrace()
            }
        }
    }
    super.onCreate(savedInstanceState)
    }

2023/11/2

[问题]


11-02 14:00:10.313 28852 28852 E AndroidRuntime: java.lang.RuntimeException: android.os.TransactionTooLargeException: data parcel size 614640 bytes
11-02 14:00:10.313 28852 28852 E AndroidRuntime: 	at android.app.ActivityClient.activityStopped(ActivityClient.java:102)
11-02 14:00:10.313 28852 28852 E AndroidRuntime: 	at android.app.servertransaction.PendingTransactionActions$StopInfo.run(PendingTransactionActions.java:143)
11-02 14:00:10.313 28852 28852 E AndroidRuntime: 	at android.os.Handler.handleCallback(Handler.java:942)
11-02 14:00:10.313 28852 28852 E AndroidRuntime: 	at android.os.Handler.dispatchMessage(Handler.java:99)
11-02 14:00:10.313 28852 28852 E AndroidRuntime: 	at android.os.Looper.loopOnce(Looper.java:210)
11-02 14:00:10.313 28852 28852 E AndroidRuntime: 	at android.os.Looper.loop(Looper.java:299)
11-02 14:00:10.313 28852 28852 E AndroidRuntime: 	at android.app.ActivityThread.main(ActivityThread.java:8252)
11-02 14:00:10.313 28852 28852 E AndroidRuntime: 	at java.lang.reflect.Method.invoke(Native Method)
11-02 14:00:10.313 28852 28852 E AndroidRuntime: 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:559)
11-02 14:00:10.313 28852 28852 E AndroidRuntime: 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:954)
11-02 14:00:10.313 28852 28852 E AndroidRuntime: Caused by: android.os.TransactionTooLargeException: data parcel size 614640 bytes
11-02 14:00:10.313 28852 28852 E AndroidRuntime: 	at android.os.BinderProxy.transactNative(Native Method)
11-02 14:00:10.313 28852 28852 E AndroidRuntime: 	at android.os.BinderProxy.transact(BinderProxy.java:646)
11-02 14:00:10.313 28852 28852 E AndroidRuntime: 	at android.app.IActivityClientController$Stub$Proxy.activityStopped(IActivityClientController.java:1266)
11-02 14:00:10.313 28852 28852 E AndroidRuntime: 	at android.app.ActivityClient.activityStopped(ActivityClient.java:99)

[描述]

当在viewpager 不断的滑动 fragment 页面的时候,导致了

2023/10/23

[问题]

Android Studio maven-metadata.xml 卡着不动原因和解决方法

可能是你的项目引入 google 等maven源导致一直下载不下来,这时可以利用国内的镜像的来替代国外的引用源

repositories {

    maven { url 'https://maven.aliyun.com/repository/central' }
    maven { url 'https://maven.aliyun.com/repository/public' }
    maven { url 'https://maven.aliyun.com/repository/jcenter' }
    maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
    maven { url 'https://maven.aliyun.com/repository/google' }
    maven { url 'https://maven.aliyun.com/nexus/content/groups/public' }
    }

2023/10/19

[问题]

targetSdkVersion 升级到 30 之后,编译安装 报错,如下:

Installation failed due to: '-124: Failed parse during installPackageLI: Targeting R+ (version 30 and above) requires the resources.arsc of installed APKs to be stored uncompressed and aligned on a 4-byte boundary'

经排查发现是美团robust 插件对资源 进行了压缩,导致了上述错误

思考:在自身资源没有错误的情况和没有压缩的情况下,也要考虑到引入的插件是否存在压缩资源的行为;(利用了排除法才定位到大概的问题所在)

20223/08/10

[问题]

RecyclerView添加头,但是头布局为空,导致ViewCompat.canScrollVertically(view,-1)始终返回true。

描述:列表第一项布局为gone 或者设置为0;但是布局管理器 仍然记录了该布局原来的高估,导致canScrollVertically 到顶部的时候,仍然还有一个高度的空间可以滑动

【解决】

【参考】 blog.csdn.net/biezhihua/a… 感谢提供了一种思路

重写RecyclerView的canScrollVertically()方法,手动判断第一个item的位置,只要getTop()大于0,就认为Item已经显示了。

 @Override
 public boolean canScrollVertically(int direction) {
     if (direction < 1) {
         boolean original = super.canScrollVertically(direction);
         if (!original || getChildAt(0) != null && getChildAt(0).getTop() >= 0) {
             return false;
         }else {
             return true;
         }
     }
     return super.canScrollVertically(direction);
 }
 

 
 int paddingTop = getPaddingTop();  
            boolean y = getLayoutManager()!= null && getLayoutManager().findViewByPosition(0) != null && (getLayoutManager().findViewByPosition(0).getTop() - paddingTop)>=0;

但是运行后发现,快速滑动的时候,会有误判的可能,所以再一次优化了方法

 @Override
 public boolean canScrollVertically(int direction) {
     if (direction < 1) {
         boolean original = super.canScrollVertically(direction);
         int paddingTop = getPaddingTop();  
         boolean isTop = getLayoutManager()!= null && getLayoutManager().findViewByPosition(0) != null && (getLayoutManager().findViewByPosition(0).getTop() - paddingTop)>=0;
         if (!original || getChildAt(0) != null && isTop) {
             return false;
         }else {
             return true;
         }
     }
     return super.canScrollVertically(direction);
 }