[app] Get logs from binder

This commit is contained in:
tehcneko 2021-02-17 17:01:38 +08:00
parent 1dd04b6f31
commit 4a39c82242
2 changed files with 84 additions and 51 deletions

View File

@ -23,11 +23,6 @@ package io.github.lsposed.manager;
import android.widget.Toast; import android.widget.Toast;
public class Constants { public class Constants {
private static final String logDir = null;
public static String getLogDir() {
return logDir;
}
public static void showErrorToast(int type) { public static void showErrorToast(int type) {
Toast.makeText(App.getInstance(), R.string.app_destroyed, Toast.LENGTH_LONG).show(); Toast.makeText(App.getInstance(), R.string.app_destroyed, Toast.LENGTH_LONG).show();

View File

@ -27,6 +27,7 @@ import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.os.ParcelFileDescriptor;
import android.util.Log; import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.Menu; import android.view.Menu;
@ -35,6 +36,8 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.TextView; import android.widget.TextView;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.ActionBar;
@ -45,37 +48,71 @@ import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.snackbar.Snackbar; import com.google.android.material.snackbar.Snackbar;
import com.google.android.material.tabs.TabLayout; import com.google.android.material.tabs.TabLayout;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream; import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Calendar; import java.util.Calendar;
import java.util.List; import java.util.List;
import java.util.Locale;
import io.github.lsposed.manager.BuildConfig; import io.github.lsposed.manager.BuildConfig;
import io.github.lsposed.manager.ConfigManager; import io.github.lsposed.manager.ConfigManager;
import io.github.lsposed.manager.Constants;
import io.github.lsposed.manager.R; import io.github.lsposed.manager.R;
import io.github.lsposed.manager.databinding.ActivityLogsBinding; import io.github.lsposed.manager.databinding.ActivityLogsBinding;
import io.github.lsposed.manager.databinding.DialogInstallWarningBinding; import io.github.lsposed.manager.databinding.DialogInstallWarningBinding;
import io.github.lsposed.manager.databinding.ItemLogBinding; import io.github.lsposed.manager.databinding.ItemLogBinding;
import io.github.lsposed.manager.ui.activity.base.BaseActivity; import io.github.lsposed.manager.ui.activity.base.BaseActivity;
import io.github.lsposed.manager.util.LinearLayoutManagerFix; import io.github.lsposed.manager.util.LinearLayoutManagerFix;
import rikka.core.os.FileUtils;
import rikka.recyclerview.RecyclerViewKt; import rikka.recyclerview.RecyclerViewKt;
public class LogsActivity extends BaseActivity { public class LogsActivity extends BaseActivity {
private int logType = 0; private int logType = 0;
private final Path modulesLog = Paths.get(Constants.getLogDir(), "modules.log"); private final ParcelFileDescriptor modulesLog = ConfigManager.getModulesLog();
private final Path allLog = Paths.get(Constants.getLogDir(), "all.log"); private final ParcelFileDescriptor allLog = ConfigManager.getVerboseLog();
private LogsAdapter adapter; private LogsAdapter adapter;
private final Handler handler = new Handler(Looper.getMainLooper()); private final Handler handler = new Handler(Looper.getMainLooper());
private ActivityLogsBinding binding; private ActivityLogsBinding binding;
private LinearLayoutManagerFix layoutManager; private LinearLayoutManagerFix layoutManager;
ActivityResultLauncher<String> saveLogsLauncher = registerForActivityResult(new ActivityResultContracts.CreateDocument(),
uri -> {
if (uri != null) {
try {
// grantUriPermission might throw RemoteException on MIUI
grantUriPermission(BuildConfig.APPLICATION_ID, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
} catch (Exception e) {
e.printStackTrace();
}
AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> {
try {
OutputStream os = getContentResolver().openOutputStream(uri);
if (os == null) {
return;
}
ParcelFileDescriptor parcelFileDescriptor = getLogFile();
if (parcelFileDescriptor == null) {
return;
}
InputStream is = new FileInputStream(parcelFileDescriptor.getFileDescriptor());
FileUtils.copy(is, os);
os.close();
is.close();
} catch (Exception e) {
Snackbar.make(binding.snackbar, getResources().getString(R.string.logs_save_failed) + "\n" + e.getMessage(), Snackbar.LENGTH_LONG).show();
}
});
}
});
private Path getLogFile() { private ParcelFileDescriptor getLogFile() {
switch (logType) { switch (logType) {
case 0: case 0:
default: default:
@ -190,12 +227,20 @@ public class LogsActivity extends BaseActivity {
} }
private void reloadErrorLog() { private void reloadErrorLog() {
new LogsReader().execute(getLogFile()); ParcelFileDescriptor parcelFileDescriptor = getLogFile();
if (parcelFileDescriptor != null) {
new LogsReader().execute(parcelFileDescriptor.getFileDescriptor());
}
} }
private void clear() { private void clear() {
try { try {
Files.write(getLogFile(), new byte[0]); ParcelFileDescriptor parcelFileDescriptor = getLogFile();
if (parcelFileDescriptor == null) {
return;
}
OutputStream os = new FileOutputStream(parcelFileDescriptor.getFileDescriptor());
os.close();
adapter.setEmpty(); adapter.setEmpty();
Snackbar.make(binding.snackbar, R.string.logs_cleared, Snackbar.LENGTH_SHORT).show(); Snackbar.make(binding.snackbar, R.string.logs_cleared, Snackbar.LENGTH_SHORT).show();
reloadErrorLog(); reloadErrorLog();
@ -205,7 +250,27 @@ public class LogsActivity extends BaseActivity {
} }
private void send() { private void send() {
Uri uri = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID + ".fileprovider", getLogFile().toFile()); ParcelFileDescriptor parcelFileDescriptor = getLogFile();
if (parcelFileDescriptor == null) {
return;
}
Calendar now = Calendar.getInstance();
String filename = String.format(Locale.US,
"LSPosed_Verbose_%04d%02d%02d_%02d%02d%02d.log",
now.get(Calendar.YEAR), now.get(Calendar.MONTH) + 1,
now.get(Calendar.DAY_OF_MONTH), now.get(Calendar.HOUR_OF_DAY),
now.get(Calendar.MINUTE), now.get(Calendar.SECOND));
File cacheFile = new File(getCacheDir(), filename);
try {
OutputStream os = new FileOutputStream(cacheFile);
InputStream is = new FileInputStream(parcelFileDescriptor.getFileDescriptor());
FileUtils.copy(is, os);
} catch (IOException e) {
e.printStackTrace();
return;
}
Uri uri = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID + ".fileprovider", cacheFile);
Intent sendIntent = new Intent(); Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND); sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_STREAM, uri); sendIntent.putExtra(Intent.EXTRA_STREAM, uri);
@ -214,48 +279,19 @@ public class LogsActivity extends BaseActivity {
startActivity(Intent.createChooser(sendIntent, getResources().getString(R.string.menuSend))); startActivity(Intent.createChooser(sendIntent, getResources().getString(R.string.menuSend)));
} }
@SuppressLint("DefaultLocale")
private void save() { private void save() {
Calendar now = Calendar.getInstance(); Calendar now = Calendar.getInstance();
String filename = String.format( String filename = String.format(Locale.US,
"LSPosed_Verbose_%04d%02d%02d_%02d%02d%02d.log", "LSPosed_Verbose_%04d%02d%02d_%02d%02d%02d.log",
now.get(Calendar.YEAR), now.get(Calendar.MONTH) + 1, now.get(Calendar.YEAR), now.get(Calendar.MONTH) + 1,
now.get(Calendar.DAY_OF_MONTH), now.get(Calendar.HOUR_OF_DAY), now.get(Calendar.DAY_OF_MONTH), now.get(Calendar.HOUR_OF_DAY),
now.get(Calendar.MINUTE), now.get(Calendar.SECOND)); now.get(Calendar.MINUTE), now.get(Calendar.SECOND));
saveLogsLauncher.launch(filename);
Intent exportIntent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
exportIntent.addCategory(Intent.CATEGORY_OPENABLE);
exportIntent.setType("text/*");
exportIntent.putExtra(Intent.EXTRA_TITLE, filename);
startActivityForResult(exportIntent, 42);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode != RESULT_OK) {
return;
}
if (requestCode == 42) {
if (data != null) {
Uri uri = data.getData();
if (uri != null) {
try {
OutputStream os = getContentResolver().openOutputStream(uri);
if (os != null) {
Files.copy(getLogFile(), os);
}
} catch (Exception e) {
Snackbar.make(binding.snackbar, getResources().getString(R.string.logs_save_failed) + "\n" + e.getMessage(), Snackbar.LENGTH_LONG).show();
}
}
}
}
} }
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
@SuppressLint("StaticFieldLeak") @SuppressLint("StaticFieldLeak")
private class LogsReader extends AsyncTask<Path, Integer, List<String>> { private class LogsReader extends AsyncTask<FileDescriptor, Integer, List<String>> {
private AlertDialog mProgressDialog; private AlertDialog mProgressDialog;
private final Runnable mRunnable = new Runnable() { private final Runnable mRunnable = new Runnable() {
@Override @Override
@ -275,14 +311,16 @@ public class LogsActivity extends BaseActivity {
} }
@Override @Override
protected List<String> doInBackground(Path... log) { protected List<String> doInBackground(FileDescriptor... log) {
Thread.currentThread().setPriority(Thread.NORM_PRIORITY + 2); Thread.currentThread().setPriority(Thread.NORM_PRIORITY + 2);
List<String> logs = new ArrayList<>(); List<String> logs = new ArrayList<>();
try { try (InputStream inputStream = new FileInputStream(log[0]); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
logs = Files.readAllLines(log[0]); String line;
return logs; while ((line = reader.readLine()) != null) {
logs.add(line);
}
} catch (IOException e) { } catch (IOException e) {
logs.add(LogsActivity.this.getResources().getString(R.string.logs_cannot_read)); logs.add(LogsActivity.this.getResources().getString(R.string.logs_cannot_read));
if (e.getMessage() != null) { if (e.getMessage() != null) {