Skip to content

Instantly share code, notes, and snippets.

@Sinyuk7
Created January 30, 2019 08:07
Show Gist options
  • Select an option

  • Save Sinyuk7/13adfcacfe00afcf033b12e34bf4426b to your computer and use it in GitHub Desktop.

Select an option

Save Sinyuk7/13adfcacfe00afcf033b12e34bf4426b to your computer and use it in GitHub Desktop.
LogActivity.java
package com.aliyun.iot.aghanim.log;
import android.annotation.SuppressLint;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Process;
import android.support.annotation.Nullable;
import android.support.v4.widget.NestedScrollView;
import android.support.v7.app.AppCompatActivity;
import android.text.Editable;
import android.text.Html;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.text.method.LinkMovementMethod;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;
import com.aliyun.iot.aep.sdk.threadpool.ThreadPool;
import com.aliyun.iot.aghanim.R;
import com.aliyun.iot.commonapp.base.ui.LinkToast;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.concurrent.atomic.AtomicBoolean;
import cn.dreamtobe.kpswitch.util.KeyboardUtil;
import static android.text.Html.FROM_HTML_MODE_LEGACY;
/**
* @author sinyuk
* @date 2019/1/30
*/
public class LogActivity extends AppCompatActivity {
private NestedScrollView nestedScrollView;
private EditText keywordEt;
private TextView logcatView;
private Button clear;
private Button save;
private Button copy;
private RadioGroup radioGroup;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_log);
nestedScrollView = findViewById(R.id.nestedScrollView);
keywordEt = findViewById(R.id.keywordEt);
logcatView = findViewById(R.id.logcat);
clear = findViewById(R.id.clear);
radioGroup = findViewById(R.id.radioGroup);
save = findViewById(R.id.save);
copy = findViewById(R.id.copy);
findViewById(R.id.button_back).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
});
setupKeyboard();
setupRadios();
}
@SuppressLint("ClickableViewAccessibility")
private void setupKeyboard() {
nestedScrollView.setOnTouchListener(new View.OnTouchListener() {
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouch(View view, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP ||
event.getAction() == MotionEvent.ACTION_CANCEL) {
keywordEt.clearFocus();
KeyboardUtil.hideKeyboard(view);
}
return false;
}
});
keywordEt.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView textView, int i, KeyEvent keyEvent) {
if (keyEvent != null && keyEvent.getKeyCode() == KeyEvent.ACTION_DOWN) {
return false;
} else if (EditorInfo.IME_ACTION_DONE == i ||
EditorInfo.IME_ACTION_SEARCH == i ||
EditorInfo.IME_NULL == i ||
keyEvent == null ||
KeyEvent.KEYCODE_ENTER == keyEvent.getAction()) {
onCheckedChanged(radioGroup.getCheckedRadioButtonId());
keywordEt.clearFocus();
}
return false;
}
});
logcatView.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void afterTextChanged(Editable editable) {
clear.setEnabled(!TextUtils.isEmpty(editable));
save.setEnabled(!TextUtils.isEmpty(editable));
copy.setEnabled(!TextUtils.isEmpty(editable));
}
});
clear.setEnabled(false);
clear.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
clear.setEnabled(false);
onCheckedChanged(radioGroup.getCheckedRadioButtonId());
}
});
save.setEnabled(false);
save.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
saveLog(logcatView.getText().toString());
}
});
copy.setEnabled(false);
copy.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//获取剪贴板管理器:
ClipboardManager cm = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
ClipData data = ClipData.newPlainText("LOG", logcatView.getText().toString());
if (cm != null) {
cm.setPrimaryClip(data);
LinkToast.makeText(LogActivity.this, "已复制到剪切板", Toast.LENGTH_SHORT).show();
}
}
});
logcatView.setMovementMethod(LinkMovementMethod.getInstance());
}
private AtomicBoolean lock = new AtomicBoolean(false);
private void setupRadios() {
radioGroup.check(R.id.verbose);
((RadioButton) findViewById(R.id.verbose)).setChecked(true);
radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup radioGroup, int i) {
LogActivity.this.onCheckedChanged(i);
}
});
ThreadPool.MainThreadHandler.getInstance().post(new Runnable() {
@Override
public void run() {
onCheckedChanged(R.id.verbose);
}
}, 500);
}
private void onCheckedChanged(final int checkedId) {
logcatView.setText(null);
final String filter = keywordEt.getText().toString();
if (!lock.getAndSet(true)) {
ThreadPool.DefaultThreadPool.getInstance().submit(new Runnable() {
@Override
public void run() {
final String tag = getLogTag(checkedId);
final String log = getCurrentLog(tag, filter);
ThreadPool.MainThreadHandler.getInstance().post(new Runnable() {
@Override
public void run() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
logcatView.setText(Html.fromHtml(log, FROM_HTML_MODE_LEGACY));
} else {
logcatView.setText(Html.fromHtml(log));
}
refreshShowLog();
}
});
}
});
}
}
private void refreshShowLog() {
ThreadPool.MainThreadHandler.getInstance().post(new Runnable() {
@Override
public void run() {
nestedScrollView.fullScroll(ScrollView.FOCUS_DOWN);
lock.set(false);
clear.setEnabled(true);
save.setEnabled(true);
}
});
}
private String getLogTag(int id) {
if (R.id.verbose == id) {
return "V";
} else if (R.id.debug == id) {
return "D";
} else if (R.id.warn == id) {
return "W";
} else if (R.id.error == id) {
return "E";
} else if (R.id.info == id) {
return "I";
} else {
return "V";
}
}
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_UP
&& event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
KeyboardUtil.hideKeyboard(keywordEt);
return true;
}
return super.dispatchKeyEvent(event);
}
private String cmd = "logcat -v time -t %d *:%s --pid=%d";
@SuppressLint("DefaultLocale")
private String getCurrentLog(final String tag, final String filter) {
StringBuilder log = new StringBuilder();
log.append("<h3>日志:<h3/><br />");
try {
int count = 100;
if (!TextUtils.isEmpty(filter)) {
count = 200;
}
int pid = Process.myPid();
if (!TextUtils.isEmpty(filter)) {
cmd += " | grep " + filter;
}
String command = String.format(cmd, count, tag, pid);
Log.d("adb", "exec: " + command);
java.lang.Process process = Runtime.getRuntime().exec(command);
BufferedReader bufferedReader =
new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = bufferedReader.readLine();
while (null != line) {
if (!TextUtils.isEmpty(filter) && line.contains(filter)) {
String tint = "<font color=\"#7F0055\"><em>" + filter + "</em></font>";
log.append(line.replace(filter, tint)).append("<br />");
} else {
String level = line.substring(15, 25);
if (TextUtils.isEmpty(level)) {
line = "<font color=\"#7F9FBF\">" + line + "</font>";
} else if (level.contains("W/")) {
line = "<font color=\"#00CC7D\">" + line + "</font>";
} else if (level.contains("E/")) {
line = "<font color=\"#FF8000\">" + line + "</font>";
} else if (level.contains("I/")) {
line = "<font color=\"#007DCC\">" + line + "</font>";
} else {
line = "<font color=\"#7F9FBF\">" + line + "</font>";
}
log.append(line).append("<br />");
}
line = bufferedReader.readLine();
}
} catch (IOException e) {
e.printStackTrace();
}
return log.toString();
}
private void saveLog(String data) {
save.setEnabled(false);
// Get the directory for the user's public pictures directory.
final File path = Environment.getExternalStoragePublicDirectory
(Environment.DIRECTORY_DCIM + "/logs/");
// Make sure the path directory exists.
if (!path.exists()) {
path.mkdirs();
}
final File file = new File(path, generateName());
// Save your stream, don't forget to flush() it before closing it.
try {
file.createNewFile();
FileOutputStream fOut = new FileOutputStream(file);
OutputStreamWriter myOutWriter = new OutputStreamWriter(fOut);
myOutWriter.append(data);
myOutWriter.close();
fOut.flush();
fOut.close();
appendResult("<br /><em>Saved location: <em>"
+ "<font color=\"#FF8000\">" + file.getAbsolutePath() + "</font><br />"
);
} catch (IOException e) {
appendResult("<br /><em>Exception: <em>"
+ "<font color=\"#FF8000\">" + e.getLocalizedMessage() + "</font><br />"
);
}
}
private void appendResult(String result) {
String text = logcatView.getText().toString();
text = text + result;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
logcatView.setText(Html.fromHtml(text, FROM_HTML_MODE_LEGACY));
} else {
logcatView.setText(Html.fromHtml(text));
}
refreshShowLog();
}
private String generateName() {
Date date = new Date(System.currentTimeMillis());
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmm", Locale.CHINA);
return format.format(date) + ".txt";
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment