android代码保护永不闪退

android代码保护永不闪退在我们开发的过程中 再厉害的程序员也无法保证写的代码没有错误 而这里面最严重的错误 对于 android 开发来说 毫无疑问就是 app 闪退了 特别是在开发第三方 SDK 的时候 假设因为 SDK 里面报的问题 导致对方 App 崩溃了 这对 SDK 而言的打击是非常严重的 有的时候我们甚至希望 SDK 即使无法很好的工作 也不要引发对接方 App 的崩溃 下面我就来介绍两种 可以根据代码判断 只会代码所在线程死掉

大家好,我是讯享网,很高兴认识大家。

在我们开发的过程中,再厉害的程序员也无法保证写的代码没有错误,而这里面最严重的错误,对于android开发来说,毫无疑问就是app闪退了.特别是在开发第三方SDK的时候,假设因为SDK里面报的问题,导致对方App崩溃了,这对SDK而言的打击是非常严重的,有的时候我们甚至希望SDK即使无法很好的工作,也不要引发对接方App的崩溃.

下面我就来介绍两种,可以根据代码判断,只会代码所在线程死掉,但不会引发崩溃的方法:

  1. hook Thread.UncaughtExceptionHandler 的方式
  2. 代理 Thread.UncaughtExceptionHandler 的方式

hook Thread.UncaughtExceptionHandler 的方式

第一种方式就是,我们在程序启动的时候,先使用Thread.getDefaultUncaughtExceptionHandler();拿到系统的错误处理Handler对象,再次之上,我们自己创建一个 Thread.UncaughtExceptionHandler 的继承类,包裹住系统的错误处理Handler对象之后,把我们自己创建的Thread.UncaughtExceptionHandler 传递回去.
系统的Thread.UncaughtExceptionHandler的实现类是com.android.internal.os.RuntimeInit$UncaughtHandler

hook代码如下:

 public void hook() { 
    Thread.UncaughtExceptionHandler ueh = Thread.getDefaultUncaughtExceptionHandler(); if (ueh == null) { 
    mSystemUeh = null; mOtherUeh = null; Thread.setDefaultUncaughtExceptionHandler(CrashHookImpl2.this); return; } String androidUeh = "com.android.internal.os.RuntimeInit$UncaughtHandler"; String selfUeh = getClass().getName(); String currUeh = ueh.getClass().getName(); //系统的 if (androidUeh.equals(currUeh)) { 
    mSystemUeh = ueh; mOtherUeh = null; Thread.setDefaultUncaughtExceptionHandler(CrashHookImpl2.this); } else if (selfUeh.equals(currUeh)) { 
    //自己人 不处理 } else { 
    // bugly的 -> currUeh.contains("com.tencent.bugly.crashreport.crash") mSystemUeh = null; mOtherUeh = ueh; Thread.setDefaultUncaughtExceptionHandler(CrashHookImpl2.this); } return; } 

讯享网

其中,CrashHookImpl2是我们继承自Thread.UncaughtExceptionHandler 自己的实现类, 其中uncaughtException实现如下:

讯享网 @Override public void uncaughtException(Thread t, Throwable e) { 
    //-----------自己的处理,拦截除0异常------------------------------- StackTraceElement[] elements = e.getStackTrace(); for (int i = 0; i < elements.length; i++) { 
    if (e.getClass().getName().equals("java.lang.ArithmeticException")) { 
    return; } } //-----------下面的系统的uncaughtException不走,既不会崩溃--------- if (mOtherUeh != null) { 
    mOtherUeh.uncaughtException(t, e); } if (mSystemUeh != null) { 
    mSystemUeh.uncaughtException(t, e); } } 

这时候, 我们可以在程序中写一个除以0 的异常,则是不会引发崩溃的,只会引发线程的停止:


讯享网

 CrashHookImpl.getInstance().hook(); CrashHookImpl.getInstance().addCutOffExceptionHandler(new CrashHook.CutOffExceptionHandler() { 
    @Override public boolean onCutOffException(Thread t, Throwable e) { 
    StackTraceElement[] elements = e.getStackTrace(); for (int i = 0; i < elements.length; i++) { 
    if (e.getClass().getName().equals("java.lang.ArithmeticException")) { 
    return true; } } return false; } }); new Thread() { 
    @Override public void run() { 
    while (true) { 
    try { 
    Thread.sleep(1000); } catch (InterruptedException e) { 
    e.printStackTrace(); } System.out.println(100 / 0 + "hook"); String nullp = null; int a = nullp.length(); } } }.start(); 

实现类全部代码:

讯享网 import android.os.Build; import android.os.Handler; import android.os.HandlerThread; import java.util.ArrayList; import java.util.List; public class CrashHookImpl2 implements Thread.UncaughtExceptionHandler, CrashHook { 
    private static volatile CrashHookImpl2 instance = null; private Thread.UncaughtExceptionHandler mSystemUeh; private Thread.UncaughtExceptionHandler mOtherUeh; private List<CutOffExceptionHandler> exceptionHandlers; private CrashHookImpl2() { 
    exceptionHandlers = new ArrayList<>(); } @Override public void hook() { 
    Thread.UncaughtExceptionHandler ueh = Thread.getDefaultUncaughtExceptionHandler(); if (ueh == null) { 
    mSystemUeh = null; mOtherUeh = null; Thread.setDefaultUncaughtExceptionHandler(CrashHookImpl2.this); return; } String androidUeh = "com.android.internal.os.RuntimeInit$UncaughtHandler"; String selfUeh = getClass().getName(); String currUeh = ueh.getClass().getName(); //系统的 if (androidUeh.equals(currUeh)) { 
    mSystemUeh = ueh; mOtherUeh = null; Thread.setDefaultUncaughtExceptionHandler(CrashHookImpl2.this); } else if (selfUeh.equals(currUeh)) { 
    //自己人 不处理 } else { 
    // bugly的 -> currUeh.contains("com.tencent.bugly.crashreport.crash") mSystemUeh = null; mOtherUeh = ueh; Thread.setDefaultUncaughtExceptionHandler(CrashHookImpl2.this); } return; } public static CrashHookImpl2 getInstance() { 
    if (instance == null) { 
    synchronized (CrashHookImpl2.class) { 
    if (instance == null) { 
    instance = new CrashHookImpl2(); } } } return instance; } @Override public void unHook() { 
    if (mSystemUeh != null) { 
    Thread.setDefaultUncaughtExceptionHandler(mSystemUeh); return; } if (mOtherUeh != null) { 
    Thread.setDefaultUncaughtExceptionHandler(mSystemUeh); return; } Thread.setDefaultUncaughtExceptionHandler(null); return; } @Override public void addCutOffExceptionHandler(CrashHook.CutOffExceptionHandler cutOffExceptionHandler) { 
    if (cutOffExceptionHandler == null) { 
    return; } exceptionHandlers.add(cutOffExceptionHandler); } @Override public void removeCutOffExceptionHandler(CrashHook.CutOffExceptionHandler cutOffExceptionHandler) { 
    if (cutOffExceptionHandler == null) { 
    return; } exceptionHandlers.remove(cutOffExceptionHandler); } public void tryHook(final long time) { 
    if (time < 0) { 
    return; } final HandlerThread thread = new HandlerThread("hook_ch"); thread.start(); final Handler handler = new Handler(thread.getLooper()); handler.post(new Runnable() { 
    private int size = 0; @Override public void run() { 
    if (size <= (time / 200)) { 
    size++; hook(); handler.postDelayed(this, 200); } else { 
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { 
    thread.quitSafely(); } else { 
    thread.quit(); } } } }); return; } @Override public void uncaughtException(Thread t, Throwable e) { 
    for (int i = 0; i < exceptionHandlers.size(); i++) { 
    boolean consumed = exceptionHandlers.get(i).onCutOffException(t, e); if (consumed) { 
    return; } } if (mOtherUeh != null) { 
    mOtherUeh.uncaughtException(t, e); } if (mSystemUeh != null) { 
    mSystemUeh.uncaughtException(t, e); } } } 

代理 Thread.UncaughtExceptionHandler 的方式

实际上也是Hook默认的 Thread.UncaughtExceptionHandler , 但这种方式的好处是,我们自己无需创建实现Thread.UncaughtExceptionHandler接口的实现类,而只需要使用Proxy.newProxyInstance代理系统默认的Thread.UncaughtExceptionHandler就好了,这种方式比起上面一种来说,除了效果一致以外,好处可能就是可以避免一些代码的检查.

代理方式的hook代码:

 public void hook() { 
    if (hooked) { 
    return; } Thread.UncaughtExceptionHandler ueh = Thread.getDefaultUncaughtExceptionHandler(); if (ueh == null) { 
    return; } //代理逻辑 class Px implements InvocationHandler { 
    private Thread.UncaughtExceptionHandler handler; private Method uncaughtExceptionMethod; private Px(Thread.UncaughtExceptionHandler handler) { 
    this.handler = handler; try { 
    uncaughtExceptionMethod = Thread.UncaughtExceptionHandler.class.getMethod("uncaughtException", Thread.class, Throwable.class); } catch (Throwable e) { 
    } } @Override public Object invoke(Object proxy, Method method, Object[] args) { 
    //先走自己的 try { 
    if (uncaughtExceptionMethod != null && uncaughtExceptionMethod.equals(method)) { 
    if (args != null && args.length == 2) { 
    Thread thread = (Thread) args[0]; Throwable throwable = (Throwable) args[1]; for (int i = 0; i < exceptionHandlers.size(); i++) { 
    boolean cutoff = exceptionHandlers.get(i).onCutOffException(thread, throwable); if (cutoff) { 
    //截断 return null; } } } } } catch (Throwable ignored) { 
    } try { 
    //原来的 method.invoke(handler, args); } catch (Throwable ignored) { 
    } return null; } } Thread.UncaughtExceptionHandler hookedUeh = (Thread.UncaughtExceptionHandler) Proxy.newProxyInstance( ueh.getClass().getClassLoader(), ueh.getClass().getInterfaces(), new Px(ueh)); Thread.setDefaultUncaughtExceptionHandler(hookedUeh); hooked = true; } 

本种方式的全部实现代码:

讯享网 import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.ArrayList; import java.util.List; public class CrashHookImpl implements CrashHook { 
    private List<CutOffExceptionHandler> exceptionHandlers; private static volatile CrashHookImpl instance = null; private boolean hooked = false; private CrashHookImpl() { 
    exceptionHandlers = new ArrayList<>(); } public static CrashHookImpl getInstance() { 
    if (instance == null) { 
    synchronized (CrashHookImpl.class) { 
    if (instance == null) { 
    instance = new CrashHookImpl(); } } } return instance; } @Override public void hook() { 
    if (hooked) { 
    return; } Thread.UncaughtExceptionHandler ueh = Thread.getDefaultUncaughtExceptionHandler(); if (ueh == null) { 
    return; } class Px implements InvocationHandler { 
    private Thread.UncaughtExceptionHandler handler; private Method uncaughtExceptionMethod; private Px(Thread.UncaughtExceptionHandler handler) { 
    this.handler = handler; try { 
    uncaughtExceptionMethod = Thread.UncaughtExceptionHandler.class.getMethod("uncaughtException", Thread.class, Throwable.class); } catch (Throwable e) { 
    } } @Override public Object invoke(Object proxy, Method method, Object[] args) { 
    try { 
    if (uncaughtExceptionMethod != null && uncaughtExceptionMethod.equals(method)) { 
    if (args != null && args.length == 2) { 
    Thread thread = (Thread) args[0]; Throwable throwable = (Throwable) args[1]; for (int i = 0; i < exceptionHandlers.size(); i++) { 
    boolean cutoff = exceptionHandlers.get(i).onCutOffException(thread, throwable); if (cutoff) { 
    //截断 return null; } } } } } catch (Throwable ignored) { 
    } try { 
    //原来的 method.invoke(handler, args); } catch (Throwable ignored) { 
    } return null; } } Thread.UncaughtExceptionHandler hookedUeh = (Thread.UncaughtExceptionHandler) Proxy.newProxyInstance( ueh.getClass().getClassLoader(), ueh.getClass().getInterfaces(), new Px(ueh)); Thread.setDefaultUncaughtExceptionHandler(hookedUeh); hooked = true; } @Override public void unHook() { 
    if (!hooked) { 
    return; } Thread.UncaughtExceptionHandler ueh = Thread.getDefaultUncaughtExceptionHandler(); if (ueh == null) { 
    return; } Thread.setDefaultUncaughtExceptionHandler(ueh); hooked = false; } @Override public void addCutOffExceptionHandler(CutOffExceptionHandler cutOffExceptionHandler) { 
    if (cutOffExceptionHandler == null) { 
    return; } exceptionHandlers.add(cutOffExceptionHandler); } @Override public void removeCutOffExceptionHandler(CutOffExceptionHandler cutOffExceptionHandler) { 
    if (cutOffExceptionHandler == null) { 
    return; } exceptionHandlers.remove(cutOffExceptionHandler); } } 

结语

 CrashHookImpl.getInstance().hook(); //保护所有的除零崩溃 CrashHookImpl.getInstance().addCutOffExceptionHandler(new CrashHook.CutOffExceptionHandler() { 
    @Override public boolean onCutOffException(Thread t, Throwable e) { 
    if (e.getClass().getName().equals("java.lang.ArithmeticException")) { 
    //返回true,截断崩溃 return true; } return false; } }); //统计上报 CrashHookImpl.getInstance().addCutOffExceptionHandler(new CrashHook.CutOffExceptionHandler() { 
    @Override public boolean onCutOffException(Thread t, Throwable e) { 
    StackTraceElement[] elements = e.getStackTrace(); for (int i = 0; i < elements.length; i++) { 
    String msg= elements[i].getClassName()+elements[i].getMethodName()+elements[i].getLineNumber(); //上报错误 } //返回false 不截断 return false; } }); 
小讯
上一篇 2025-01-12 10:20
下一篇 2025-01-10 22:34

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/48383.html