Android 开发中不得不知道的 Tips 集合 (第三波)

Android开发技巧集锦
本文汇总了Android开发中常见的问题及解决办法,包括应用崩溃处理、IntentService与Thread的区别、Gradle打包错误解决、WiFi调试真机及系统源码阅读技巧。

相关文章 1.Android 开发中不得不知道的 Tips 集合 (持续更新 ing) 2.Android 开发中不得不知道的 Tips 集合 (第二波))

1.应用又崩溃啦!!!

开发过程中,受种种因素影响(机型适配问题、程序员技术功底等),已发布上线的应用难免回出现Crash,如果我们不做处理,崩溃后系统会弹出对话框(xxx应用已停止).这时候用户手一哆嗦就直接卸载了有木有。so,既然开发人员不能阻止Crash的出现,那就得从崩溃后的提示入手了,将对用户的影响降到最低。

解决方案: 利用Thread的setDefaultUncaughtExceptionHandler方法,将未知的异常进行捕获,然后友好的提示用户,重新启动应用。(伸手党可直接拿走哈) 有图有真相:

1.新建CrashHandler类,这个类负责捕获未处理的异常

/**
 * Created by weixinjie on 2017/6/1.
 */

public class CrashHandler implements Thread.UncaughtExceptionHandler {
    private Thread.UncaughtExceptionHandler mDefaultHandler;
    public static final String TAG = "CatchExcep";
    SampleApplication application;

    public CrashHandler(SampleApplication application) {
        //获取系统默认的UncaughtException处理器
        mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
        this.application = application;
    }

    @Override
    public void uncaughtException(Thread thread, Throwable ex) {
        if (!handleException(ex) && mDefaultHandler != null) {
            //如果用户没有处理则让系统默认的异常处理器来处理
            mDefaultHandler.uncaughtException(thread, ex);
        } else {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                Log.e(TAG, "error : ", e);
            }
            Intent intent = new Intent(application.getApplicationContext(), MainActivity.class);
            PendingIntent restartIntent = PendingIntent.getActivity(
                    application.getApplicationContext(), 0, intent,
                    PendingIntent.FLAG_CANCEL_CURRENT);
            //退出程序
            AlarmManager mgr = (AlarmManager) application.getSystemService(Context.ALARM_SERVICE);
            mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 1000,
                    restartIntent); // 1秒钟后重启应用
            System.exit(0);
        }
    }

    /**
     * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.
     *
     * @param ex
     * @return true:如果处理了该异常信息;否则返回false.
     */
    private boolean handleException(Throwable ex) {
        if (ex == null) {
            return false;
        }
        //使用Toast来显示异常信息
        new Thread() {
            @Override
            public void run() {
                Looper.prepare();
                Toast.makeText(application, "应用异常,正在重启", Toast.LENGTH_LONG).show();
                Looper.loop();
            }
        }.start();
        return true;
    }
}


    /**
     * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.
     *
     * @param ex
     * @return true:如果处理了该异常信息;否则返回false.
     */
    private boolean handleException(Throwable ex) {
        if (ex == null) {
            return false;
        }
        //使用Toast来显示异常信息
        new Thread() {
            @Override
            public void run() {
                Looper.prepare();
                ToastUtil.toastLong(R.string.error_for_restart);
                Looper.loop();
            }
        }.start();
        return true;
    }
}
复制代码

2.在应用的Application的onCreate方法中调用如下代码:

  @Override
    public void onCreate() {
        initCrashHandler();
    }

 private void initCrashHandler() {
        //设置该CrashHandler为程序的默认处理器
        CrashHandler catchExcep = new CrashHandler(this);
        Thread.setDefaultUncaughtExceptionHandler(catchExcep);
    }
复制代码

3.在清单文件中将自定义的Application注册一下.

2.为什么要用IntentService而不用Thread

面试的时候大家经常会被问IntentService跟Thread有什么区别吧?比如App升级的时候,去服务端下载apk包的时候为什么要开一个IntertService而不是Thread. Answer:我们要从Android系统的5大进程级别来看待这个事情,分别为“前台进程”,“可视进程”,“服务进程”,“后台进程”,“空进程”.当系统的内存不足时,会根据进程的级别来回收这些进程.即回收的顺序为:“空进程”->...->“前台进程”.很明显,如果用户按下home键之后,我们的进程会变成一个后台进程,此时很容易被系统回收掉,那咱们在Thread中所做的操作就白扯了,而如果我们开一个IntentService的话,我们的进程会变成一个Service进程,被回收的几率就大大降低了。 当然,这种问题我们不应该只停留在理论阶段,应付面试是一方面,我们还是要多看系统的文档,这也是我等菜鸟通往高级工程师必不可少的一环。 祭上官方文档:https://developer.android.com/guide/components/processes-and-threads.html?hl=zh-cn (科学上网哈)

3.Gradle脚本中已删除的sdk,发布release包的事后报NoClassDefFoundError错误

缘由:项目在内测阶段用到了BugTags来指Bug (BugTags确实可以大大提高测试的效率,建议大家在内测阶段接入他们的服务进行测试) ,发布release版本的时候,为了减少包体,便将该sdk从gradle脚本中剔除了。然后打出release包之后。一打开就闪退,并且报如下错误

我当时就郁闷了,Gradle脚本中都删了咋还报类找不到?然后花了一下午的时间挨个疑点进行排查——没错是新版的gradle的锅。 解决方案: 找到 gradle --> wrapper --> gradle-wrapper.properties distributionUrl=https://services.gradle.org/distributions/gradle-2.14.1-all.zip android gradle build 插件版本 classpath 'com.android.tools.build:gradle:2.2.3'

4.用adb进行wifi链接真机调试(不需root呦)。

方案如下: 1.手机与你的电脑要在同一个局域网下 2.配置你电脑上的adb命令。不要告诉我你不会配,请自行百度哈。 3.用usb链接电脑跟手机,在命令窗口输入:[ adb tcpip 5555 ]

4.查看你手机的ip地址:设置-WLAN-[点击你正在使用的wifi],例如我手机的ip地址为: 192.168.31.237 5.在adb命令中输入: adb connect 192.168.31.237

6.拔掉的usb线,以后就可以用wifi调试这部手机啦。看下你的as中的Android Monitor模块,正常来说已经可以出现要调试的手机了。(搞不定的叫我微信,或留言哈)

5.通往大牛的路上,怎能不看系统源码

前段时间项目赶,没时间继续我的看系统源码计划,还好,现在项目进入正常迭代周期,我又有时间可以折腾源码啦。 推荐给大家一个Chrome插件:https://chrome.google.com/webstore/search/Android%20SDK%20Reference%20Search%20 安装之后,你用Chrome浏览器去Android Developer上查api的时候,会自动加入这么一个东东,你就可以enjoy看系统源码带给你的充实啦。

楼主用的Mac,用Sublime+CTag折腾了一套源码阅读器,用了半年了感觉很棒。需要的同学留言,下次分享给大家哈。

About Me

contact wayvalue
mailweixinjie1993@gmail.com
wechatW2006292
githubhttps://github.com/weixinjie
bloghttps://juejin.im/user/57673c83207703006bb92bf6
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值