问题0025 - 异常汇总

547 阅读3分钟

1."Only fullscreen opaque activities can request orientation "

  1. 原因
  • Android O 禁止透明Activity在xml中指定屏幕方向,否则会抛出异常
  • Google提交
  1. 几种修改方法
  • 方法1:Activity对应的theme,windowIsTranslucent及windowIsFloating修改为false
    <item name="android:windowIsTranslucent">false</item>
    <item name="android:windowIsFloating">false</item>
    
  • 方法2:对于透明Activity,xml不要设置屏幕方向
    去掉Activity的:
    android:screenOrientation="**"
    
  1. 文章

2. 使用系统ViewPager报异常:IllegalArgumentException: pointerIndex out of range

Fatal Exception: java.lang.IllegalArgumentException: pointerIndex out of range
       at android.view.MotionEvent.nativeGetAxisValue(MotionEvent.java)
       at android.view.MotionEvent.getX(MotionEvent.java:2401)
       at androidx.viewpager.widget.ViewPager.onTouchEvent(SourceFile:35)
       at android.view.View.dispatchTouchEvent(View.java:14392)
       at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3138)

原因:

这个bug是系统抛出的bug,涉及到多点触控. pointerIndex out of range代表系统ViewPager处理事件时候,拿到的'手指个数'不对,导致通过手指索引获取指定手指的坐标信息越界.

解决方案:

直接重写ViewPager,重写其 onTouchEvent 及 onInterceptTouchEvent . 添加异常捕获逻辑.

public class CustomViewPager extends ViewPager {

   public CustomViewPager(Context context) {
       super(context);
   }

   public CustomViewPager(Context context, AttributeSet attrs) {
       super(context, attrs);
   }

   @Override
   public boolean onTouchEvent(MotionEvent ev) {
       try {
           return super.onTouchEvent(ev);
       } catch (Exception e) {
           e.printStackTrace();
       }
       return false;
   }

   @Override
   public boolean onInterceptTouchEvent(MotionEvent ev) {
       try {
           return super.onInterceptTouchEvent(ev);
       } catch (Exception e) {
           e.printStackTrace();
       }
       return false;
   }
}

3. 修改系统配置(如切换导航)导致Activity重建,进而触发Fragment重建.有时会报异常: Unable to instantiate fragment XXXFragment: could not find Fragment constructor

2022-05-21 15:22:19.850 23439-23439/*** E/CrashHandler: name: main ; e:java.lang.RuntimeException: Unable to start activity ComponentInfo{***}: androidx.fragment.app.Fragment$InstantiationException: Unable to instantiate fragment ***Fragment: could not find Fragment constructor ;
2022-05-21 15:22:19.850 23439-23439/*** E/CrashHandler: err:
    java.lang.RuntimeException: Unable to start activity ComponentInfo{***}: androidx.fragment.app.Fragment$InstantiationException: Unable to instantiate fragment ***Fragment: could not find Fragment constructor
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3584)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3756)
        at android.app.ActivityThread.handleRelaunchActivityInner(ActivityThread.java:5661)
        at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:5567)
        at android.app.servertransaction.ActivityRelaunchItem.execute(ActivityRelaunchItem.java:69)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ClientTransactionHandler.executeTransaction(ClientTransactionHandler.java:58)
        at android.app.ActivityThread.handleRelaunchActivityLocally(ActivityThread.java:5620)
        at android.app.ActivityThread.access$3600(ActivityThread.java:265)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2205)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:236)
        at android.app.ActivityThread.main(ActivityThread.java:8087)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:620)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1011)
     Caused by: androidx.fragment.app.Fragment$InstantiationException: Unable to instantiate fragment com.android.wallpaper.picker.CategorySelectorFragment: could not find Fragment constructor
        at androidx.fragment.app.Fragment.instantiate(Fragment.java:628)
        at androidx.fragment.app.FragmentContainer.instantiate(FragmentContainer.java:57)
        at androidx.fragment.app.FragmentManager$3.instantiate(FragmentManager.java:483)
        at androidx.fragment.app.FragmentStateManager.<init>(FragmentStateManager.java:85)
        at androidx.fragment.app.FragmentManager.restoreSaveState(FragmentManager.java:2728)
        at androidx.fragment.app.FragmentController.restoreSaveState(FragmentController.java:198)
        at androidx.fragment.app.FragmentActivity$2.onContextAvailable(FragmentActivity.java:149)
        at androidx.activity.contextaware.ContextAwareHelper.dispatchOnContextAvailable(ContextAwareHelper.java:99)
        at androidx.activity.ComponentActivity.onCreate(ComponentActivity.java:357)
        at androidx.fragment.app.FragmentActivity.onCreate(FragmentActivity.java:273)
        at ***Activity.onCreate(BxTopLevelPickerActivity.java:47)
        at android.app.Activity.performCreate(Activity.java:8142)
        at android.app.Activity.performCreate(Activity.java:8114)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3557)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3756) 
        at android.app.ActivityThread.handleRelaunchActivityInner(ActivityThread.java:5661) 
        at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:5567) 
        at android.app.servertransaction.ActivityRelaunchItem.execute(ActivityRelaunchItem.java:69) 
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 
        at android.app.ClientTransactionHandler.executeTransaction(ClientTransactionHandler.java:58) 
        at android.app.ActivityThread.handleRelaunchActivityLocally(ActivityThread.java:5620) 
        at android.app.ActivityThread.access$3600(ActivityThread.java:265) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2205) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loop(Looper.java:236) 
        at android.app.ActivityThread.main(ActivityThread.java:8087) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:620) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1011) 
     Caused by: java.lang.NoSuchMethodException: ***Fragment.<init> []
        at java.lang.Class.getConstructor0(Class.java:2332)
        at java.lang.Class.getConstructor(Class.java:1728)
        at androidx.fragment.app.Fragment.instantiate(Fragment.java:613)
        at androidx.fragment.app.FragmentContainer.instantiate(FragmentContainer.java:57) 
        at androidx.fragment.app.FragmentManager$3.instantiate(FragmentManager.java:483) 
        at androidx.fragment.app.FragmentStateManager.<init>(FragmentStateManager.java:85) 
        at androidx.fragment.app.FragmentManager.restoreSaveState(FragmentManager.java:2728) 
        at androidx.fragment.app.FragmentController.restoreSaveState(FragmentController.java:198) 
        at androidx.fragment.app.FragmentActivity$2.onContextAvailable(FragmentActivity.java:149) 
        at androidx.activity.contextaware.ContextAwareHelper.dispatchOnContextAvailable(ContextAwareHelper.java:99) 
        at androidx.activity.ComponentActivity.onCreate(ComponentActivity.java:357) 
        at androidx.fragment.app.FragmentActivity.onCreate(FragmentActivity.java:273) 
        at ***Activity.onCreate(BxTopLevelPickerActivity.java:47) 
        at android.app.Activity.performCreate(Activity.java:8142) 
        at android.app.Activity.performCreate(Activity.java:8114) 
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309) 
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3557) 
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3756) 
        at android.app.ActivityThread.handleRelaunchActivityInner(ActivityThread.java:5661) 
        at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:5567) 
        at android.app.servertransaction.ActivityRelaunchItem.execute(ActivityRelaunchItem.java:69) 
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 
        at android.app.ClientTransactionHandler.executeTransaction(ClientTransactionHandler.java:58) 
        at android.app.ActivityThread.handleRelaunchActivityLocally(ActivityThread.java:5620) 
        at android.app.ActivityThread.access$3600(ActivityThread.java:265) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2205) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loop(Looper.java:236) 
        at android.app.ActivityThread.main(ActivityThread.java:8087) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:620) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1011
  1. 原因: 该Fragment缺少无参构造方法.
  2. 看源码
    /**
     * Create a new instance of a Fragment with the given class name.  This is
     * the same as calling its empty constructor, setting the {@link ClassLoader} on the
     * supplied arguments, then calling {@link #setArguments(Bundle)}.
     *
     * @param context The calling context being used to instantiate the fragment.
     * This is currently just used to get its ClassLoader.
     * @param fname The class name of the fragment to instantiate.
     * @param args Bundle of arguments to supply to the fragment, which it
     * can retrieve with {@link #getArguments()}.  May be null.
     * @return Returns a new fragment instance.
     * @throws InstantiationException If there is a failure in instantiating
     * the given fragment class.  This is a runtime exception; it is not
     * normally expected to happen.
     * @deprecated Use {@link FragmentManager#getFragmentFactory()} and
     * {@link FragmentFactory#instantiate(ClassLoader, String)}, manually calling
     * {@link #setArguments(Bundle)} on the returned Fragment.
     */
    @Deprecated
    @NonNull
    public static Fragment instantiate(@NonNull Context context, @NonNull String fname,
            @Nullable Bundle args) {
        try {
            Class<? extends Fragment> clazz = FragmentFactory.loadFragmentClass(
                    context.getClassLoader(), fname);
//这里获取的是其无参构造函数.
//说明Activity重建后,触发Fragment重建会使用默认的无参构造方法创建Fragment实例.
            Fragment f = clazz.getConstructor().newInstance();
            if (args != null) {
                args.setClassLoader(f.getClass().getClassLoader());
                f.setArguments(args);
            }
            return f;
        } catch (java.lang.InstantiationException e) {
            throw new InstantiationException("Unable to instantiate fragment " + fname
                    + ": make sure class name exists, is public, and has an"
                    + " empty constructor that is public", e);
        } catch (IllegalAccessException e) {
            throw new InstantiationException("Unable to instantiate fragment " + fname
                    + ": make sure class name exists, is public, and has an"
                    + " empty constructor that is public", e);
        } catch (NoSuchMethodException e) {
            throw new InstantiationException("Unable to instantiate fragment " + fname
                    + ": could not find Fragment constructor", e);
        } catch (InvocationTargetException e) {
            throw new InstantiationException("Unable to instantiate fragment " + fname
                    + ": calling Fragment constructor caused an exception", e);
        }
    }
  1. 修复方法: 在对应Fragment中添加无参构造方法
public XXXFragment(){
    super();
}

4. Can't determine type for tag*** . 在build过程中,一致报异常,提示某个依赖库的某个attr属性无法识别

大图地址

build异常.png

  1. 原因未知
  2. 修改方法
  • 自己尝试将gradle文件中依赖库的版本中的 "+" 去掉.使用具体的版本号.改了之后就好了.日了狗.
  • 修改前
final String ANDROID_X_VERSION = "1+"

dependencies {
    implementation 'androidx.constraintlayout:constraintlayout:2.+'
    implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.+'
    implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.+'
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    implementation "androidx.recyclerview:recyclerview:${ANDROID_X_VERSION}"
    implementation "androidx.cardview:cardview:${ANDROID_X_VERSION}"
    implementation "androidx.appcompat:appcompat:${ANDROID_X_VERSION}"
    implementation "androidx.exifinterface:exifinterface:${ANDROID_X_VERSION}"
    implementation "com.google.android.material:material:${ANDROID_X_VERSION}"
  • 修改后
final String ANDROID_X_VERSION = "1"

dependencies {
    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
    implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.4.1'
    implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.1'
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    implementation "androidx.recyclerview:recyclerview:${ANDROID_X_VERSION}"
    implementation "androidx.cardview:cardview:${ANDROID_X_VERSION}"
    implementation "androidx.appcompat:appcompat:${ANDROID_X_VERSION}"
    implementation "androidx.exifinterface:exifinterface:${ANDROID_X_VERSION}"
    implementation "com.google.android.material:material:${ANDROID_X_VERSION}"