1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.example.android.common.logger;
17 
18 import android.app.Activity;
19 import android.content.Context;
20 import android.util.AttributeSet;
21 import android.widget.TextView;
22 
23 /**
24  * Simple TextView which is used to output log data received through the LogNode interface.
25  */
26 public class LogView extends TextView implements LogNode {
27 
LogView(Context context)28     public LogView(Context context) {
29         super(context);
30     }
31 
LogView(Context context, AttributeSet attrs)32     public LogView(Context context, AttributeSet attrs) {
33         super(context, attrs);
34     }
35 
LogView(Context context, AttributeSet attrs, int defStyle)36     public LogView(Context context, AttributeSet attrs, int defStyle) {
37         super(context, attrs, defStyle);
38     }
39 
40     /**
41      * Formats the log data and prints it out to the LogView.
42      *
43      * @param priority Log level of the data being logged.  Verbose, Error, etc.
44      * @param tag      Tag for for the log data.  Can be used to organize log statements.
45      * @param msg      The actual message to be logged. The actual message to be logged.
46      * @param tr       If an exception was thrown, this can be sent along for the logging
47      *                 facilities
48      *                 to extract and print useful information.
49      */
50     @Override
println(int priority, String tag, String msg, Throwable tr)51     public void println(int priority, String tag, String msg, Throwable tr) {
52 
53         String priorityStr = null;
54 
55         // For the purposes of this View, we want to print the priority as readable text.
56         switch (priority) {
57             case android.util.Log.VERBOSE:
58                 priorityStr = "VERBOSE";
59                 break;
60             case android.util.Log.DEBUG:
61                 priorityStr = "DEBUG";
62                 break;
63             case android.util.Log.INFO:
64                 priorityStr = "INFO";
65                 break;
66             case android.util.Log.WARN:
67                 priorityStr = "WARN";
68                 break;
69             case android.util.Log.ERROR:
70                 priorityStr = "ERROR";
71                 break;
72             case android.util.Log.ASSERT:
73                 priorityStr = "ASSERT";
74                 break;
75             default:
76                 break;
77         }
78 
79         // Handily, the Log class has a facility for converting a stack trace into a usable string.
80         String exceptionStr = null;
81         if (tr != null) {
82             exceptionStr = android.util.Log.getStackTraceString(tr);
83         }
84 
85         // Take the priority, tag, message, and exception, and concatenate as necessary
86         // into one usable line of text.
87         final StringBuilder outputBuilder = new StringBuilder();
88 
89         String delimiter = "\t";
90         appendIfNotNull(outputBuilder, priorityStr, delimiter);
91         appendIfNotNull(outputBuilder, tag, delimiter);
92         appendIfNotNull(outputBuilder, msg, delimiter);
93         appendIfNotNull(outputBuilder, exceptionStr, delimiter);
94 
95         // In case this was originally called from an AsyncTask or some other off-UI thread,
96         // make sure the update occurs within the UI thread.
97         ((Activity) getContext()).runOnUiThread((new Thread(new Runnable() {
98             @Override
99             public void run() {
100                 // Display the text we just generated within the LogView.
101                 appendToLog(outputBuilder.toString());
102             }
103         })));
104 
105         if (mNext != null) {
106             mNext.println(priority, tag, msg, tr);
107         }
108     }
109 
getNext()110     public LogNode getNext() {
111         return mNext;
112     }
113 
setNext(LogNode node)114     public void setNext(LogNode node) {
115         mNext = node;
116     }
117 
118     /**
119      * Takes a string and adds to it, with a separator, if the bit to be added isn't null. Since
120      * the logger takes so many arguments that might be null, this method helps cut out some of the
121      * agonizing tedium of writing the same 3 lines over and over.
122      *
123      * @param source    StringBuilder containing the text to append to.
124      * @param addStr    The String to append
125      * @param delimiter The String to separate the source and appended strings. A tab or comma,
126      *                  for instance.
127      * @return The fully concatenated String as a StringBuilder
128      */
appendIfNotNull(StringBuilder source, String addStr, String delimiter)129     private StringBuilder appendIfNotNull(StringBuilder source, String addStr, String delimiter) {
130         if (addStr != null) {
131             if (addStr.length() == 0) {
132                 delimiter = "";
133             }
134 
135             return source.append(addStr).append(delimiter);
136         }
137         return source;
138     }
139 
140     // The next LogNode in the chain.
141     LogNode mNext;
142 
143     /** Outputs the string as a new line of log data in the LogView. */
appendToLog(String s)144     public void appendToLog(String s) {
145         append("\n" + s);
146     }
147 
148 
149 }
150