Android进阶之路 - 异常汇总

所遇异常,皆为我工作中所遇,持续更新 ~

孪生篇:AndroidStudio编写、编译期间常见问题

1. 空指针 Error:null value in entry: annotationProcessorOutputFolder=null(条目中的空值)

  • 通用解决方案:删除根目录下的 .gradle文件,之后重新编译使用

2. android.view.WindowManager$BadTokenException: Unable to add window – token null is not valid; is your activity running? (视图顺序问题)

  • 出现场景:使用popupWindow在activity初始化的时候报出了 BadTokenException 异常,通过查询发现是初始化视图的时候,我们的依赖的视图还没有创建好(popupWindow的展示,需要寄存在外部的parentView上),在同一时间进行初始化导致出错

  • 解决方案:popupWindow延时加载,只需要几百毫秒即可,代码如下 :

 CountDownTimer timerSp = new CountDownTimer(400, 100) {
            @Override
            public void onTick(long millisUntilFinished) {

            }

            @Override
            public void onFinish() {
		       //初始化popupWiondow,我这里是用来版本检测的弹框
                versionDetection();
            }
        };
        timerSp.start();

3. 报错 FileUriExposedException(Andorid7.0隐私保护提升)

  • 出现场景:版本升级之后进行安装,安装时报出FileUriExposedException错误
  • 出现原因:Android7.0之后,因之前对文件保护不足,故进行了优化
  • 解决方式:Android7.0兼容适配 - 共享文件

4. Executing tasks: [:app:assembleBaiduDebug](命名重复)

  • 出现场景:清单文件修改代码之后
  • 出现原因:某些命名重复了(可能是第三方的)
  • 解决方式:修改重复命名,同时尝试通过 clean,rebuild 查看是否可以修复此问题

5. Execution failed for task ':app:preDebugAndroidTestBuild

  • 出现原因:发生这类型的错误,是当我们修改了.build中的 compileSdkVersion,产生所依赖的dependency与当前版本不一致导致的

  • 解决方式

 build->Rebuid-project

6. 隐藏软键盘的出现的异常,因为是之前出现的,所以我忘了异常的名字是什么,大概意思就是针对的目标不一样,一个是针对的是单个事件,另一个针对的是一个整体

  • 错误方式
 InputMethodManager inputMethodManager = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
        if (inputMethodManager.isActive()) {    
                    inputMethodManager.hideSoftInputFromWindow(getActivity().getCurrentFocus().getWindowToken(), 0); 
        }
  • 正式方式
 InputMethodManager inputMethodManager = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
        if (inputMethodManager.isActive()) {
            inputMethodManager.hideSoftInputFromWindow(new View(getContext()).getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
        }

7. android.view.WindowManager$BadTokenException(首次进入界面弹出popupWindow报错)

  • 出现原因 : 主依赖的activity视图没有渲染完毕,但是我们已经设置了popup的依赖展示范围,此时指向的是一个NULL的状态!
  • 解决方式
//重写此方法
@Override
public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);
    //在这里写popupWindow的代码既可~~~~
}

8. Intent数据传递报错 java.lang.RuntimeException: Parcel: unable to marshal value com.zhym.friendcircule.Photo@41fcd5c8 (通用错误:ava.lang.RuntimeException: Parcel: unable to marshal value)

  • 出现原因
    其一:intent传递的数据类型是一个实体类,或者是List内包含这样一个数据类似的实体类~
    其二:这个实体类 没有实现序列化 !

  • 解决方式
    给我们使用的实体类实现Serializable接口,如:

 public class Photo implements Serializable

9. java.lang.IllegalArgumentException: Both dimensions must be greater than 0 (扫描二维码报错)

在这里插入图片描述
解决方式 一

将我们自己的application 继承 ZApplication
在这里插入图片描述
解决方式 二

将ZApplication内的配置信息放入到我们自己的Application
在这里插入图片描述

10. DexArchiveMergerException(重复依赖、引用 )

报错:Execution failed for task ':app:transformDexArchiveWithDexMergerForDebug'

  • 出现原因:重复依赖某个库或某个包,导致报出异常

  • 查看重复依赖:通过gradle命令查看重复依赖,在android studio命令窗口中输入以下命令:

 	gradle -q dependencies

注:如命令无效,请查收 AndroidStudio内允许Gralde命令

  • 解决方式 - 1
    查看build.gradle中是否有重复导入的依赖,如果有的话就删除掉,重新编译

  • 解决方式 - 2
    如查看build.gradle中无重复引用,那么继续查看对应lib文件夹内的 jar包 是否与build.gradle内的依赖重复!如果有的话删掉其一,重新编译

  • 解决方式 - 3
    查看依赖之间,是否存在子母包,如A、B三方框架都包含C依赖~ 那么需要使用以下方式剔除其中的重复依赖,也可以借鉴这里~

//运用exclude group 关键字
 compile ('com.***.***:XXX:1.0.0') { // 所加的第三方框架A或B
    exclude group: 'com.android.support', module:'design'     // 加载时排除框架中的design包
 }
 //剔除或忽略对应重复依赖包之后,这个异常按理就已经处理咯 ~~

检查一下build.gradle中是否有类似

 compile(name: 'class', ext: 'jar')

这样的代码,如果有的话,可以修改为下面这种写法:

 compile files('libs/class.jar')
  • 解决方式 - 5

1.然后在 build.gradle 文件中的 defaultConfig 配置中添加配置

 multiDexEnabled true

截图如下
在这里插入图片描述
2.build.gradle(app)导入依赖

 implementation 'com.android.support:multidex:1.0.3'
  • 解决方式 - 6
android {
  ...
  compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
  }
}
  • 解决方式 - 7

通过gradlew命令,查看重复依赖,然后移除对应框架内的重复包!

 //这种方式解决项目包重复依赖问题非常有效。
 gradlew :demo:dependencies

11. java.lang.IllegalArgumentException: n must be positive(非法参数异常:约束必须为正)

出现原因

根据 非法参数异常:约束必须为正 去解析异常的话,可以看出我们的需求值>=0;

而我对应的场景是因为使用Random().nextInt(n)随机数导致的;

Random().nextInt(n)表示对应输入的随机数在0~n之间,但是不能等于n !所以如果这个n=0 ,那么起点可以 =0,终点 !=0,而你的值恰恰是0 就产生了一个矛盾,故此抛出了上方异常

解决方式

这里我用的是递归方式,如如果之前我们得出的随机数为0的话,我们就继续随机,直到随机数不为0为止 ~

  • 使用场景
    private void wantData() {
        int randomInt = mRandom.nextInt(5);
        int nowRandomInt =  getRecursion(randomInt,5);
    }
  • 处理方式(递归)
  //封装递归 - randomInt不可为0
    private int getRecursion(int randomInt, int wantData) {
        if (randomInt != 0) {
            return randomInt;
        }
        return getRecursion(mRandom.nextInt(wantData), wantData);
    }

12. IllegalArgumentException: Viewnot attached to window manager(Dialog异常关闭所引起)

出现原因

Dialog未关闭而Activity已关闭

解决方式

在Activity的onStop或onDestory生命周期内写以下方法,

if(getActivity() != null && !getActivity().isFinishing()) { 
	mDialog.dismiss(); 
} 

13. java.lang.RuntimeException: Unable to instantiate activity ComponentInfo 或 java.io.IOException: Error while Installing APK. Error while Installing APK(真机运行)

解决方式

打开IDE,进入File—>Setting—>Build,Execution,Deployment—>Instant Run

将enable instant run to hot swap code/resource changes on deploy的勾去掉
在这里插入图片描述

14. com.android.ddmlib.AdbCommandRejectedException: device offline Error while Installing APK

出现原因
这个问题是adb被杀死了,重新启动一下就可以

解决方式
可以在sdk的文件中找到plattform-tools,到这个文件夹里面去可以找到adb,

双击adb,就可以重新启动了

15. IllegalStateException:Task already scheduled or cancelled(计时Task)

出现原因:创建计时器后,定时打开和关闭计时器。可以随时暂停,更改关闭和打开时间

出现问题:定时器的TimerTask只能被shceduler一次,所以当再次调用时,就会抛出该IllegalStateException:Task already scheduled or cancelled.

解决方式

通过改变标识符state来达到目的,但state是默认的,访问权限只有包和同个类,所以我们通过反射来设置

        timer = new Timer();
        task = RelayOpenTask.getIntance();
        //task.setMap(uuidMap, this);
         Field field;
        try {
            field = TimerTask.class.getDeclaredField("state");
            field.setAccessible(true);
            field.set(task, 0);
        } catch (NoSuchFieldException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

16. JavaBinder: !!! FAILED BINDER TRANSACTION !!! 或 FAILED Binder Transaction(数据太大)

因为在As中的报错中有看到此项信息,故此记录一波,主要借鉴 于此 ~,解决方法未亲测,有问题及时留言即可 ~

出现原因:用Intent传递数据时,Bitmap不能大于40KB,而根据官网的介绍,Intent传递数据有限制,最大为1M左右

解决方法

  • 方式 1:尽可能的不再Intent中传递Bitmap。可以先把要传递的bitmap保存在SD中,Intent中传递时用url地址代替
  • 方式 2:如果实在要对Bitmap进行传递,可以先对其压缩
`/**
 * 压缩图片(如果无效可自行百度一个压缩图片的方法)
 * @param image
 * @return
 */
public static Bitmap compressImage(Bitmap image) {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    image.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
    int options = 100;
    while (baos.toByteArray().length / 1024 > 100) {  //循环判断如果压缩后图片是否大于100kb,大于继续压缩
        baos.reset();//重置baos即清空baos
        image.compress(Bitmap.CompressFormat.JPEG, options, baos);//这里压缩options%,把压缩后的数据存放到baos中
        options -= 10;//每次都减少10
    }
    ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());//把压缩后的数据baos存放到ByteArrayInputStream中
    Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);//把ByteArrayInputStream数据生成图片
    return bitmap;
}
  • 方式 3:将要传递的数据改成全局变量

如果要传递的量大,上述的方法2也是于事无补的。比如说我的上述问题,即使在bean中去掉bitmap变量,还是会报错,因为我要传递的数组实在太大了!换一种思路,将要传递的数据放在一个固定的生命周期中的值里,随时赋值随时取值,想到这,放在Application中很合适 ~

public class MediaApplication extends Application {
    // 用于传递的图片数据
    private List<MediaFileBean> mPhotoList;
    private static MediaApplication mInstance;
    @Override
    public void onCreate() {
        super.onCreate();
        mInstance = this;
    }

    public synchronized static MediaApplication getInstance() {
        return mInstance;
    }

    public void setPhotoList(ArrayList<MediaFileBean> list){
        this.mPhotoList = list;
    }

    public List<MediaFileBean> getPhotoList(){
        return this.mPhotoList;
    }
}

17. ActivityNotFoundException(未找到该Activty)

Java.lang.ClassNotFoundException
E/AndroidRuntime(1875):Caused by: Java.lang.ClassNotFoundException:XXXXX in loader dalvik.system.PathClassLoader[/data/app/XXXX.apk]

  • 首先查看AndroidManifest清单文件中是否已注册该Activity
  • 如已注册查看注册的Activity是否使用如 </activity Android:name=".xxxActivity">,而不是全称
    </activityandroid:name="目标包名及具体路径.xxxActivity">
  • 引用三方库(jar包)内的class,编译使用时发布成apk,此时可能不包含该类(建议忽略,此处仅做为笔记)

android.content.ActivityNotFoundException
01-01 16:09:04.714: E/AndroidRuntime(2924): android.content.ActivityNotFoundException:NoActivity found to handle Intent{ act=myapp.action.test1 }

问题代码

<activity android:name="com.x210.intentfilters.OneActivity"
		android:label="oneActivity">  
            <intent-filter>
                <actionandroid:name="myapp.action.test1" />
                <actionandroid:name="myapp.action.test2" />  
            </intent-filter>
 </activity>

解决方式

由于在通过Intent调用Activity时,Android默认会自动添加CATEGORY_DEFAULT类别属性,故在Filter配置中CATEGORY_DEFAULT是不可缺少的;

//<Intent-filter>节点中加入以下配置:
<category android:name="android.intent.category.DEFAULT"/>

18. java.lang.ArithmeticException:divide by zero (除数为0)

在Java中 除数不能为零,需仔细检查代码是否有机会出现除数为零的情况 ~

19. 使用比较器引起 java.lang.IllegalArgumentException: Comparison method violates its general contract!

出现原因
使用compare比较器,必须有返回0的操作,如下代码只有返回1和-1

Collections.sort(intervals, new Comparator<Interval>() {
        @Override
        public int compare(Interval o1, Interval o2) {
        if (o1.start>o2.start){
         	return 1;
         }
        else{
        	return -1;
        }
     }
});

解决方式

在返回中加入0的可选项

Collections.sort(intervals, new Comparator<Interval>() {
        @Override
        public int compare(Interval o1, Interval o2) {
        if (o1.start>o2.start){
         	return 1;
         }
        if (o1.start==o2.start){
         	return 0;
         }
        else{
        	return -1;
        }
     }
});

20.com.android.builder.internal.aapt.v2.Aapt2Exception: AAPT2 error: check logs for details(生成签名apk时报错)

  • gradle.properties中加入以下配置
 android.enableAapt2=false
  • build gradle 中加入以下配置
 aaptOptions.cruncherEnabled = false
 aaptOptions.useNewCruncher = false

具体如下

buildTypes {
        release {
            aaptOptions.cruncherEnabled = false
            aaptOptions.useNewCruncher = false
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
  • 重启、clean、rebuild

21. 请求接口,报错 HTTP FAILED/System.err : java.net.UnknownServiceException: CLEARTEXT communication to 192.168.ip ~ not permitte by network security policy(Android9.0http请求限制)

出现原因

  • 由于 Android P(版本27以上) 限制了明文流量的网络请求,非加密的流量请求都会被系统禁止掉
  • 如果当前应用的请求是 htttp 请求,而非 https ,这样就会导系统禁止当前应用进行该请求

解决方式:Android 9.0 兼容适配

22.请求接口,报错 Expected URL scheme ‘http’ or ‘https’ but no colon was found

出现原因:请求的url为空导致的问题,一般都是自己粗心导致

解决方式:debug逻辑顺序,查看传入的url值是否为空,如逻辑比较弱,可以将url的值存在sp内进行用前赋值 ~

感谢您的提问。要实现指南针功能,我们需要使用Android的Sensor(传感器)API。下面是一些基本步骤: 1. 获取SensorManager对象。您可以通过以下方式获取: ```java SensorManager sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); ``` 2. 获取方向传感器。我们需要使用Android设备上的方向传感器来获取设备的方向。您可以使用以下代码获取方向传感器: ```java Sensor orientationSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION); ``` 请注意,`Sensor.TYPE_ORIENTATION`在Android API级别20中被弃用。您应该使用`Sensor.TYPE_ROTATION_VECTOR`代替。 3. 创建SensorEventListener。我们需要实现`SensorEventListener`接口来接收传感器数据。您可以使用以下代码来创建一个SensorEventListener: ```java private final SensorEventListener sensorEventListener = new SensorEventListener() { @Override public void onSensorChanged(SensorEvent event) { // 当传感器数据更新时调用此方法 // 在这里更新指南针方向 } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { // 当传感器精度发生变化时调用此方法 } }; ``` 4. 注册SensorEventListener。您需要在Activity的生命周期方法(例如`onResume()`)中注册`SensorEventListener`,以便在传感器数据更新时接收通知。您可以使用以下代码进行注册: ```java sensorManager.registerListener(sensorEventListener, orientationSensor, SensorManager.SENSOR_DELAY_UI); ``` 请注意,`SENSOR_DELAY_UI`表示传感器数据应该以与UI线程更新相同的频率更新。您可以使用其他常量来指定更新频率。 5. 实现指南针方向。您需要使用传感器数据来计算设备的方向,并更新指南针方向。您可以使用以下代码来获取设备的方向: ```java float[] orientationValues = new float[3]; SensorManager.getOrientation(event.values, orientationValues); float azimuth = Math.toDegrees(orientationValues[0]); ``` 请注意,`azimuth`表示设备的方向,以度为单位。 6. 更新指南针方向。您需要在UI线程中更新指南针方向。您可以使用以下代码来更新指南针方向: ```java runOnUiThread(new Runnable() { @Override public void run() { compassView.setDirection(azimuth); } }); ``` 请注意,`compassView`是一个自定义视图,用于绘制指南针。 这些是实现指南针功能的基本步骤。您需要根据自己的需求进行调整和修改。祝您好运!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

远方那座山

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值