Created
January 30, 2019 08:07
-
-
Save Sinyuk7/13adfcacfe00afcf033b12e34bf4426b to your computer and use it in GitHub Desktop.
LogActivity.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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