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("

日志:


"); 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 = "" + filter + ""; log.append(line.replace(filter, tint)).append("
"); } else { String level = line.substring(15, 25); if (TextUtils.isEmpty(level)) { line = "" + line + ""; } else if (level.contains("W/")) { line = "" + line + ""; } else if (level.contains("E/")) { line = "" + line + ""; } else if (level.contains("I/")) { line = "" + line + ""; } else { line = "" + line + ""; } log.append(line).append("
"); } 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("
Saved location: " + "" + file.getAbsolutePath() + "
" ); } catch (IOException e) { appendResult("
Exception: " + "" + e.getLocalizedMessage() + "
" ); } } 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"; } }