Android Log 源码介绍

1.关于Log源码介绍

  • Log对象,它位于android framework层utils包下,是一个final class类

    • 源码如下所示,可以看到其实final类,所以不能通过继承Log类的方式实现自身的日志工具类,一般可以通过定义Log成员变量的方式,封装Log工具方法。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    public final class Log {

    /**
    * Priority constant for the println method; use Log.v.
    */
    public static final int VERBOSE = 2;

    /**
    * Priority constant for the println method; use Log.d.
    */
    public static final int DEBUG = 3;

    /**
    * Priority constant for the println method; use Log.i.
    */
    public static final int INFO = 4;

    /**
    * Priority constant for the println method; use Log.w.
    */
    public static final int WARN = 5;

    /**
    * Priority constant for the println method; use Log.e.
    */
    public static final int ERROR = 6;

    /**
    * Priority constant for the println method.
    */
    public static final int ASSERT = 7;

    private Log() {
    }

    /**
    * Send a {@link #VERBOSE} log message.
    * @param tag Used to identify the source of a log message. It usually identifies
    * the class or activity where the log call occurs.
    * @param msg The message you would like logged.
    */
    public static int v(String tag, String msg) {
    return println(LOG_ID_MAIN, VERBOSE, tag, msg);
    }

    /**
    * Send a {@link #VERBOSE} log message and log the exception.
    * @param tag Used to identify the source of a log message. It usually identifies
    * the class or activity where the log call occurs.
    * @param msg The message you would like logged.
    * @param tr An exception to log
    */
    public static int v(String tag, String msg, Throwable tr) {
    return println(LOG_ID_MAIN, VERBOSE, tag, msg + '\n' + getStackTraceString(tr));
    }

    /**
    * Send a {@link #DEBUG} log message.
    * @param tag Used to identify the source of a log message. It usually identifies
    * the class or activity where the log call occurs.
    * @param msg The message you would like logged.
    */
    public static int d(String tag, String msg) {
    return println(LOG_ID_MAIN, DEBUG, tag, msg);
    }

    /**
    * Send a {@link #DEBUG} log message and log the exception.
    * @param tag Used to identify the source of a log message. It usually identifies
    * the class or activity where the log call occurs.
    * @param msg The message you would like logged.
    * @param tr An exception to log
    */
    public static int d(String tag, String msg, Throwable tr) {
    return println(LOG_ID_MAIN, DEBUG, tag, msg + '\n' + getStackTraceString(tr));
    }

    /**
    * Send an {@link #INFO} log message.
    * @param tag Used to identify the source of a log message. It usually identifies
    * the class or activity where the log call occurs.
    * @param msg The message you would like logged.
    */
    public static int i(String tag, String msg) {
    return println(LOG_ID_MAIN, INFO, tag, msg);
    }

    /**
    * Send a {@link #INFO} log message and log the exception.
    * @param tag Used to identify the source of a log message. It usually identifies
    * the class or activity where the log call occurs.
    * @param msg The message you would like logged.
    * @param tr An exception to log
    */
    public static int i(String tag, String msg, Throwable tr) {
    return println(LOG_ID_MAIN, INFO, tag, msg + '\n' + getStackTraceString(tr));
    }

    /**
    * Send a {@link #WARN} log message.
    * @param tag Used to identify the source of a log message. It usually identifies
    * the class or activity where the log call occurs.
    * @param msg The message you would like logged.
    */
    public static int w(String tag, String msg) {
    return println(LOG_ID_MAIN, WARN, tag, msg);
    }

    /**
    * Send a {@link #WARN} log message and log the exception.
    * @param tag Used to identify the source of a log message. It usually identifies
    * the class or activity where the log call occurs.
    * @param msg The message you would like logged.
    * @param tr An exception to log
    */
    public static int w(String tag, String msg, Throwable tr) {
    return println(LOG_ID_MAIN, WARN, tag, msg + '\n' + getStackTraceString(tr));
    }

    /*
    * Send a {@link #WARN} log message and log the exception.
    * @param tag Used to identify the source of a log message. It usually identifies
    * the class or activity where the log call occurs.
    * @param tr An exception to log
    */
    public static int w(String tag, Throwable tr) {
    return println(LOG_ID_MAIN, WARN, tag, getStackTraceString(tr));
    }

    /**
    * Send an {@link #ERROR} log message.
    * @param tag Used to identify the source of a log message. It usually identifies
    * the class or activity where the log call occurs.
    * @param msg The message you would like logged.
    */
    public static int e(String tag, String msg) {
    return println(LOG_ID_MAIN, ERROR, tag, msg);
    }

    /**
    * Send a {@link #ERROR} log message and log the exception.
    * @param tag Used to identify the source of a log message. It usually identifies
    * the class or activity where the log call occurs.
    * @param msg The message you would like logged.
    * @param tr An exception to log
    */
    public static int e(String tag, String msg, Throwable tr) {
    return println(LOG_ID_MAIN, ERROR, tag, msg + '\n' + getStackTraceString(tr));
    }

    /**
    * Handy function to get a loggable stack trace from a Throwable
    * @param tr An exception to log
    */
    public static String getStackTraceString(Throwable tr) {
    if (tr == null) {
    return "";
    }

    // This is to reduce the amount of log spew that apps do in the non-error
    // condition of the network being unavailable.
    Throwable t = tr;
    while (t != null) {
    if (t instanceof UnknownHostException) {
    return "";
    }
    t = t.getCause();
    }

    StringWriter sw = new StringWriter();
    PrintWriter pw = new PrintWriter(sw);
    tr.printStackTrace(pw);
    pw.flush();
    return sw.toString();
    }

    /**
    * Low-level logging call.
    * @param priority The priority/type of this log message
    * @param tag Used to identify the source of a log message. It usually identifies
    * the class or activity where the log call occurs.
    * @param msg The message you would like logged.
    * @return The number of bytes written.
    */
    public static int println(int priority, String tag, String msg) {
    return println(LOG_ID_MAIN, priority, tag, msg);
    }

    /** @hide */ public static final int LOG_ID_MAIN = 0;
    /** @hide */ public static final int LOG_ID_RADIO = 1;
    /** @hide */ public static final int LOG_ID_EVENTS = 2;
    /** @hide */ public static final int LOG_ID_SYSTEM = 3;
    /** @hide */ public static final int LOG_ID_CRASH = 4;

    /** @hide */ @SuppressWarnings("unused")
    public static int println(int bufID,
    int priority, String tag, String msg) {
    return 0;
    }
    }
阅读更多

Android version 的作用

1.CompileSdkVersion的作用

  • compileSdkVersion 告诉 Gradle 用哪个 Android SDK 版本编译你的应用。使用任何新添加的 API 就需要使用对应 Level 的 Android SDK。
  • 需要强调的是修改 compileSdkVersion 不会改变运行时的行为。当你修改了 compileSdkVersion 的时候,可能会出现新的编译警告、编译错误,但新的 compileSdkVersion 不会被包含到 APK 中:它纯粹只是在编译的时候使用。(你真的应该修复这些警告,他们的出现一定是有原因的)
阅读更多

Android Fragment 源码分析

一 Fragment操作方法

Fragment的操作是一种事务操作,什么是事务?🤔简单来说就是一个原子操作,要么被成功执行,否则原来的操作会回滚,各个操作彼此之间互不干扰。我们先整体看下Fragment的操作
序列图。

fragment_operation_sequence

阅读更多

Android 代码混淆

01.什么是混淆

  • 混淆代码
    • 混淆分为两种代码混淆和资源文件混淆。实际的产品研发中为了防止自己的劳动成果被别人窃取,混淆代码能有效防止apk文件被反编译,进而查看源代码。
  • Android如何混淆
    • android提供了Progurd方式来混淆apk中的代码,其核心的逻辑是在代码层将一些易懂的源代码类名,方法名称替换成毫无意义的a、b、c、d…,这样当第三方反编译出你的Apk文件时,看到的源代码也无法还原其本身的逻辑,或者代码中方法,类,对象等变成无法阅读的字母。
阅读更多

Android Fragment 填坑

01.getActivity()空指针

  • 遇到的问题

    • 可能你遇到过getActivity()返回null,或者平时运行完好的代码,在“内存重启”之后,调用getActivity()的地方却返回null,报了空指针异常。
  • 出现的原因分析

    • 大多数情况下的原因:你在调用了getActivity()时,当前的Fragment已经onDetach()了宿主Activity。
阅读更多

Android Fragment 进阶

01.什么是内存重启

  • 安卓app有一种特殊情况,就是 app运行在后台的时候,系统资源紧张的时候导致把app的资源全部回收(杀死app的进程),这时把app再从后台返回到前台时,app会重启。这种情况下文简称为:“内存重启”。(屏幕旋转等配置变化也会造成当前Activity重启,本质与“内存重启”类似)
  • 在系统要把app回收之前,系统会把Activity的状态保存下来,Activity的FragmentManager负责把Activity中的Fragment保存起来。在“内存重启”后,Activity的恢复是从栈顶逐步恢复,Fragment会在宿主Activity的onCreate方法调用后紧接着恢复(从onAttach生命周期开始)。
阅读更多

Android Fragment 基础

01.什么是Fragment

  • 什么是Fragment
    • 可以简单的理解为,Fragment是显示在Activity中的Activity。它可以显示在Activity中,然后它也可以显示出一些内容。因为它拥有自己的生命周期,可以接受处理用户的事件,并且你可以在一个Activity中动态的添加,替换,移除不同的Fragment,因此对于信息的展示具有很大的便利性。
    • 作为 view 界面的一部分,Fragment 的存在必须依附于 FragmentActivit使用,并且与 FragmentActivit 一样,拥有自己的独立的生命周期,同时处理用户的交互动作。同一个 FragmentActivit 可以有一个或多个 Fragment 作为界面内容,同样Fragment也可以拥有多个子Fragment,并且可以动态添加、删除 Fragment,让UI的重复利用率和易修改性得以提升,同样可以用来解决部分屏幕适配问题。
阅读更多

Android BroadCastReceiver 二

01.监听网络状态变化

  • 写一个监听网络状态变化工具类

    • 首先需要一个用来监测当前网络状态的工具类
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    class NetworkUtils {

    /**
    * 标记当前网络状态,分别是:移动数据、Wifi、未连接、网络状态已公布
    */
    public enum State {
    MOBILE, WIFI, UN_CONNECTED, PUBLISHED
    }

    /**
    * 为了避免因多次接收到广播反复提醒的情况而设置的标志位,用于缓存收到新的广播前的网络状态
    */
    private static State tempState;

    /**
    * 获取当前网络连接状态
    *
    * @param context Context
    * @return 网络状态
    */
    public static State getConnectState(Context context) {
    ConnectivityManager manager = (ConnectivityManager) context.
    getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo = null;
    if (manager != null) {
    networkInfo = manager.getActiveNetworkInfo();
    }
    State state = State.UN_CONNECTED;
    if (networkInfo != null && networkInfo.isAvailable()) {
    if (isMobileConnected(context)) {
    state = State.MOBILE;
    } else if (isWifiConnected(context)) {
    state = State.WIFI;
    }
    }
    if (state.equals(tempState)) {
    return State.PUBLISHED;
    }
    tempState = state;
    return state;
    }

    private static boolean isMobileConnected(Context context) {
    return isConnected(context, ConnectivityManager.TYPE_MOBILE);
    }

    private static boolean isWifiConnected(Context context) {
    return isConnected(context, ConnectivityManager.TYPE_WIFI);
    }

    private static boolean isConnected(Context context, int type) {
    //getAllNetworkInfo() 在 API 23 中被弃用
    //getAllNetworks() 在 API 21 中才添加
    ConnectivityManager manager = (ConnectivityManager) context.
    getSystemService(Context.CONNECTIVITY_SERVICE);
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
    NetworkInfo[] allNetworkInfo = new NetworkInfo[0];
    if (manager != null) {
    allNetworkInfo = manager.getAllNetworkInfo();
    }
    for (NetworkInfo info : allNetworkInfo) {
    if (info.getType() == type) {
    return info.isAvailable();
    }
    }
    } else {
    Network[] networks = new Network[0];
    if (manager != null) {
    networks = manager.getAllNetworks();
    }
    for (Network network : networks) {
    NetworkInfo networkInfo = manager.getNetworkInfo(network);
    if (networkInfo.getType() == type) {
    return networkInfo.isAvailable();
    }
    }
    }
    return false;
    }
    }
阅读更多

Android BroadCastReceiver 三

01.广播实现原理

  • Android中的广播使用了设计模式中的观察者模式:基于消息的发布/订阅事件模型。
    • 因此,Android将广播的发送者 和 接收者 解耦,使得系统方便集成,更易扩展
  • 模型中有3个角色:
    • 1.消息订阅者(广播接收者)
    • 2.消息发布者(广播发布者)
    • 3.消息中心(AMS,即Activity Manager Service
阅读更多

Android Activity 探坑分析

01.Activity异常生命周期

  • 虽然前面也说了这个异常的生命周期,但是还是有些疑问?
  • 异常条件会调用什么方法
    • 当非人为终止Activity时,比如系统配置发生改变时导致Activity被杀死并重新创建、资源内存不足导致低优先级的Activity被杀死,会调用 onSavaInstanceState() 来保存状态。该方法调用在onStop之前,但和onPause没有时序关系。
    • 有人会问,onSaveInstanceState()与onPause()的区别,onSaveInstanceState()适用于对临时性状态的保存,而onPause()适用于对数据的持久化保存。
阅读更多