mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-06-12 05:07:45 +02:00
Log fragment completed
This commit is contained in:
@ -2,6 +2,7 @@ package com.topjohnwu.magisk;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.support.annotation.IdRes;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.design.widget.NavigationView;
|
||||
import android.support.v4.app.Fragment;
|
||||
@ -30,6 +31,9 @@ public class WelcomeActivity extends AppCompatActivity implements NavigationView
|
||||
@BindView(R.id.drawer_layout) DrawerLayout drawer;
|
||||
@BindView(R.id.nav_view) NavigationView navigationView;
|
||||
|
||||
@IdRes
|
||||
private int mSelectedId = R.id.modules;// for now
|
||||
|
||||
@Override
|
||||
protected void onCreate(final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
@ -51,21 +55,31 @@ public class WelcomeActivity extends AppCompatActivity implements NavigationView
|
||||
}
|
||||
};
|
||||
|
||||
drawer.setDrawerListener(toggle);
|
||||
drawer.addDrawerListener(toggle);
|
||||
toggle.syncState();
|
||||
|
||||
navigationView.setNavigationItemSelectedListener(this);
|
||||
//noinspection ResourceType
|
||||
mSelectedId = savedInstanceState == null ? mSelectedId : savedInstanceState.getInt(SELECTED_ITEM_ID);
|
||||
navigationView.setCheckedItem(mSelectedId);
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
if (savedInstanceState == null) {
|
||||
mDrawerHandler.removeCallbacksAndMessages(null);
|
||||
mDrawerHandler.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
navigate(savedInstanceState.getInt(SELECTED_ITEM_ID));
|
||||
navigate(mSelectedId);
|
||||
}
|
||||
}, 250);
|
||||
}
|
||||
|
||||
navigationView.setNavigationItemSelectedListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
|
||||
outState.putInt(SELECTED_ITEM_ID, mSelectedId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -79,7 +93,7 @@ public class WelcomeActivity extends AppCompatActivity implements NavigationView
|
||||
|
||||
@Override
|
||||
public boolean onNavigationItemSelected(@NonNull final MenuItem menuItem) {
|
||||
menuItem.setChecked(true);
|
||||
mSelectedId = menuItem.getItemId();
|
||||
mDrawerHandler.removeCallbacksAndMessages(null);
|
||||
mDrawerHandler.postDelayed(new Runnable() {
|
||||
@Override
|
||||
|
@ -27,7 +27,7 @@ public class ModulesAdapter extends RecyclerView.Adapter<ModulesAdapter.ViewHold
|
||||
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row, parent, false);
|
||||
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_module, parent, false);
|
||||
|
||||
return new ViewHolder(view);
|
||||
}
|
||||
|
@ -1,5 +1,275 @@
|
||||
package com.topjohnwu.magisk.ui;
|
||||
|
||||
public class LogFragment extends android.support.v4.app.Fragment {
|
||||
// private static final String MAGISK_LOG = "/cache/magisk.log";
|
||||
import android.Manifest;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.os.Handler;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.HorizontalScrollView;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.ScrollView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.ui.utils.Utils;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.Calendar;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
|
||||
public class LogFragment extends Fragment {
|
||||
|
||||
private static final File MAGISK_LOG = new File("/cache/magisk.log");
|
||||
|
||||
@BindView(R.id.txtLog) TextView txtLog;
|
||||
@BindView(R.id.svLog) ScrollView svLog;
|
||||
@BindView(R.id.hsvLog) HorizontalScrollView hsvLog;
|
||||
|
||||
@BindView(R.id.progressBar) ProgressBar progressBar;
|
||||
|
||||
private MenuItem mClickedMenuItem;
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
setHasOptionsMenu(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.log_fragment, container, false);
|
||||
ButterKnife.bind(this, view);
|
||||
|
||||
txtLog.setTextIsSelectable(true);
|
||||
|
||||
reloadErrorLog();
|
||||
|
||||
setHasOptionsMenu(true);
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
inflater.inflate(R.menu.menu_log, menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
mClickedMenuItem = item;
|
||||
switch (item.getItemId()) {
|
||||
case R.id.menu_refresh:
|
||||
reloadErrorLog();
|
||||
return true;
|
||||
case R.id.menu_send:
|
||||
try {
|
||||
send();
|
||||
} catch (NullPointerException ignored) {
|
||||
}
|
||||
return true;
|
||||
case R.id.menu_save:
|
||||
save();
|
||||
return true;
|
||||
case R.id.menu_clear:
|
||||
clear();
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
private void reloadErrorLog() {
|
||||
new LogsReader().execute(MAGISK_LOG);
|
||||
svLog.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
svLog.scrollTo(0, txtLog.getHeight());
|
||||
}
|
||||
});
|
||||
hsvLog.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
hsvLog.scrollTo(0, 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void clear() {
|
||||
try {
|
||||
new FileOutputStream(MAGISK_LOG).close();
|
||||
MAGISK_LOG.delete();
|
||||
txtLog.setText(R.string.log_is_empty);
|
||||
|
||||
Snackbar.make(txtLog, R.string.logs_cleared, Snackbar.LENGTH_SHORT).show();
|
||||
|
||||
reloadErrorLog();
|
||||
} catch (IOException e) {
|
||||
Toast.makeText(getActivity(), getResources().getString(R.string.logs_clear_failed) + "\n" + e.getMessage(), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
|
||||
private void send() {
|
||||
Intent sendIntent = new Intent();
|
||||
sendIntent.setAction(Intent.ACTION_SEND);
|
||||
sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(save()));
|
||||
sendIntent.setType("application/html");
|
||||
startActivity(Intent.createChooser(sendIntent, getResources().getString(R.string.menuSend)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
if (requestCode == 0) {
|
||||
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
if (mClickedMenuItem != null) {
|
||||
new Handler().postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
onOptionsItemSelected(mClickedMenuItem);
|
||||
}
|
||||
}, 500);
|
||||
}
|
||||
} else {
|
||||
Snackbar.make(txtLog, R.string.permissionNotGranted, Snackbar.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("DefaultLocale")
|
||||
private File save() {
|
||||
if (ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
|
||||
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 0);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
|
||||
Snackbar.make(txtLog, R.string.sdcard_not_writable, Snackbar.LENGTH_LONG).show();
|
||||
return null;
|
||||
}
|
||||
|
||||
Calendar now = Calendar.getInstance();
|
||||
String filename = String.format(
|
||||
"magisk_%s_%04d%02d%02d_%02d%02d%02d.log", "error",
|
||||
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 dir = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Magisk/");
|
||||
dir.mkdir();
|
||||
|
||||
File targetFile = new File(dir, filename);
|
||||
|
||||
try {
|
||||
FileInputStream in = new FileInputStream(MAGISK_LOG);
|
||||
FileOutputStream out = new FileOutputStream(targetFile);
|
||||
byte[] buffer = new byte[1024];
|
||||
int len;
|
||||
while ((len = in.read(buffer)) > 0) {
|
||||
out.write(buffer, 0, len);
|
||||
}
|
||||
in.close();
|
||||
out.close();
|
||||
|
||||
Toast.makeText(getActivity(), targetFile.toString(), Toast.LENGTH_LONG).show();
|
||||
return targetFile;
|
||||
} catch (IOException e) {
|
||||
Toast.makeText(getActivity(), getResources().getString(R.string.logs_save_failed) + "\n" + e.getMessage(), Toast.LENGTH_LONG).show();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private class LogsReader extends AsyncTask<File, Integer, String> {
|
||||
|
||||
private static final int MAX_LOG_SIZE = 1000 * 1024; // 1000 KB
|
||||
|
||||
private long skipLargeFile(BufferedReader is, long length) throws IOException {
|
||||
if (length < MAX_LOG_SIZE)
|
||||
return 0;
|
||||
|
||||
long skipped = length - MAX_LOG_SIZE;
|
||||
long yetToSkip = skipped;
|
||||
do {
|
||||
yetToSkip -= is.skip(yetToSkip);
|
||||
} while (yetToSkip > 0);
|
||||
|
||||
int c;
|
||||
do {
|
||||
c = is.read();
|
||||
if (c == -1)
|
||||
break;
|
||||
skipped++;
|
||||
} while (c != '\n');
|
||||
|
||||
return skipped;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
Utils.executeCommand("chmod 777 /cache");
|
||||
Utils.executeCommand("chmod 777 /cache/magisk.log");
|
||||
txtLog.setText("");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String doInBackground(File... log) {
|
||||
Thread.currentThread().setPriority(Thread.NORM_PRIORITY + 2);
|
||||
|
||||
StringBuilder llog = new StringBuilder(15 * 10 * 1024);
|
||||
try {
|
||||
File logfile = log[0];
|
||||
BufferedReader br;
|
||||
br = new BufferedReader(new FileReader(logfile));
|
||||
long skipped = skipLargeFile(br, logfile.length());
|
||||
if (skipped > 0) {
|
||||
llog.append("-----------------\n");
|
||||
llog.append("Log too long");
|
||||
llog.append("\n-----------------\n\n");
|
||||
}
|
||||
|
||||
char[] temp = new char[1024];
|
||||
int read;
|
||||
while ((read = br.read(temp)) > 0) {
|
||||
llog.append(temp, 0, read);
|
||||
}
|
||||
br.close();
|
||||
} catch (IOException e) {
|
||||
llog.append("Cannot read log:\n");
|
||||
llog.append(e.getMessage());
|
||||
}
|
||||
|
||||
return llog.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(String llog) {
|
||||
progressBar.setVisibility(View.GONE);
|
||||
txtLog.setText(llog);
|
||||
|
||||
if (llog.length() == 0)
|
||||
txtLog.setText(R.string.log_is_empty);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ import java.util.List;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
|
||||
public class ModulesFragment extends android.support.v4.app.Fragment {
|
||||
public class ModulesFragment extends Fragment {
|
||||
|
||||
private static final String MAGISK_PATH = "/magisk";
|
||||
private static final String MAGISK_CACHE_PATH = "/cache/magisk";
|
||||
|
@ -1,4 +1,6 @@
|
||||
package com.topjohnwu.magisk.ui;
|
||||
|
||||
public class RootFragment extends android.support.v4.app.Fragment {
|
||||
import android.support.v4.app.Fragment;
|
||||
|
||||
public class RootFragment extends Fragment {
|
||||
}
|
||||
|
Reference in New Issue
Block a user