Add logger for install mod screen

This commit is contained in:
khanhduytran0 2020-09-24 17:48:23 +07:00
parent e6e288e15d
commit 1bd9c02194
6 changed files with 303 additions and 147 deletions

View File

@ -2,79 +2,118 @@ package net.kdt.pojavlaunch;
import android.graphics.*; import android.graphics.*;
import android.os.*; import android.os.*;
import android.support.v7.app.*;
import android.view.*; import android.view.*;
import android.widget.*;
import com.oracle.dalvik.*; import com.oracle.dalvik.*;
import java.io.*; import java.io.*;
import java.util.*;
import java.lang.reflect.*; import java.lang.reflect.*;
import java.util.*;
public class InstallModActivity extends AppCompatActivity public class InstallModActivity extends LoggableActivity
{ {
private TextureView mTextureView; private TextureView mTextureView;
private LinearLayout contentLog;
private TextView textLog;
private ScrollView contentScroll;
private ToggleButton toggleLog;
private File logFile;
private PrintStream logStream;
private boolean isLogAllow;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.install_mod); setContentView(R.layout.install_mod);
final File modFile = (File) getIntent().getExtras().getSerializable("modFile"); try {
logFile = new File(Tools.MAIN_PATH, "latestlog.txt");
mTextureView = findViewById(R.id.installmod_surfaceview); logFile.delete();
mTextureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener(){ logFile.createNewFile();
logStream = new PrintStream(logFile.getAbsolutePath());
this.contentLog = (LinearLayout) findViewById(R.id.content_log_layout);
this.contentScroll = (ScrollView) findViewById(R.id.content_log_scroll);
this.textLog = (TextView) contentScroll.getChildAt(0);
this.toggleLog = (ToggleButton) findViewById(R.id.content_log_toggle_log);
this.toggleLog.setChecked(false);
// this.textLogBehindGL = (TextView) findViewById(R.id.main_log_behind_GL);
// this.textLogBehindGL.setTypeface(Typeface.MONOSPACE);
this.textLog.setTypeface(Typeface.MONOSPACE);
this.toggleLog.setOnCheckedChangeListener(new ToggleButton.OnCheckedChangeListener(){
@Override
public void onCheckedChanged(CompoundButton button, boolean isChecked) {
isLogAllow = isChecked;
appendToLog("");
}
});
JREUtils.redirectAndPrintJRELog(this);
final File modFile = (File) getIntent().getExtras().getSerializable("modFile");
@Override mTextureView = findViewById(R.id.installmod_surfaceview);
public void onSurfaceTextureAvailable(SurfaceTexture tex, int w, int h) { mTextureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener(){
try {
Surface surface = new Surface(tex);
Field field = surface.getClass().getDeclaredField("mNativeObject");
field.setAccessible(true);
JREUtils.setupBridgeSurfaceAWT((long) field.get(surface));
} catch (Throwable th) {
Tools.showError(InstallModActivity.this, th, true);
}
new Thread(new Runnable(){
@Override
public void run() {
launchJavaRuntime(modFile);
// finish();
}
}).start();
}
@Override @Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture tex) { public void onSurfaceTextureAvailable(SurfaceTexture tex, int w, int h) {
return false; try {
} Surface surface = new Surface(tex);
Field field = surface.getClass().getDeclaredField("mNativeObject");
field.setAccessible(true);
JREUtils.setupBridgeSurfaceAWT((long) field.get(surface));
} catch (Throwable th) {
Tools.showError(InstallModActivity.this, th, true);
}
@Override new Thread(new Runnable(){
public void onSurfaceTextureSizeChanged(SurfaceTexture tex, int w, int h) { @Override
public void run() {
} launchJavaRuntime(modFile);
// finish();
}
}).start();
}
@Override @Override
public void onSurfaceTextureUpdated(SurfaceTexture tex) { public boolean onSurfaceTextureDestroyed(SurfaceTexture tex) {
return false;
} }
});
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture tex, int w, int h) {
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture tex) {
}
});
} catch (Throwable th) {
Tools.showError(this, th, true);
}
} }
public void forceClose(View v) { public void forceClose(View v) {
MainActivity.dialogForceClose(this); MainActivity.dialogForceClose(this);
} }
public void openLogOutput(View v) {
contentLog.setVisibility(View.VISIBLE);
}
public void closeLogOutput(View view) {
contentLog.setVisibility(View.GONE);
// mIsResuming = true;
}
private void launchJavaRuntime(File modFile) { private void launchJavaRuntime(File modFile) {
try { try {
List<String> javaArgList = new ArrayList<String>(); List<String> javaArgList = new ArrayList<String>();
javaArgList.add(Tools.homeJreDir + "/bin/java"); javaArgList.add(Tools.homeJreDir + "/bin/java");
// javaArgList.add("-Xms512m"); Tools.getJavaArgs(this, javaArgList);
javaArgList.add("-Xmx512m");
javaArgList.add("-Djava.home=" + Tools.homeJreDir);
javaArgList.add("-Djava.io.tmpdir=" + getCacheDir().getAbsolutePath());
javaArgList.add("-Dos.name=Linux");
File cacioAwtLibPath = new File(Tools.MAIN_PATH, "cacioawtlib"); File cacioAwtLibPath = new File(Tools.MAIN_PATH, "cacioawtlib");
if (cacioAwtLibPath.exists()) { if (cacioAwtLibPath.exists()) {
@ -107,4 +146,17 @@ public class InstallModActivity extends AppCompatActivity
Tools.showError(this, th, true); Tools.showError(this, th, true);
} }
} }
@Override
public void appendToLog(final String text, boolean checkAllow) {
logStream.print(text);
if (checkAllow && !isLogAllow) return;
textLog.post(new Runnable(){
@Override
public void run() {
textLog.append(text);
contentScroll.fullScroll(ScrollView.FOCUS_DOWN);
}
});
}
} }

View File

@ -1,8 +1,9 @@
package net.kdt.pojavlaunch; package net.kdt.pojavlaunch;
import android.system.*;
import java.io.*;
import android.content.*; import android.content.*;
import android.system.*;
import android.util.*;
import java.io.*;
import net.kdt.pojavlaunch.prefs.*; import net.kdt.pojavlaunch.prefs.*;
public class JREUtils public class JREUtils
@ -31,7 +32,42 @@ public class JREUtils
dlopen(nativeLibDir + "/libgl04es.so"); dlopen(nativeLibDir + "/libgl04es.so");
} }
} }
public static native void redirectLogcat();
public static void redirectAndPrintJRELog(LoggableActivity act) {
JREUtils.redirectLogcat();
Log.v("jrelog","Log starts here");
Thread t = new Thread(() -> {
try {
Log.i("jrelog-logcat","Clearing logcat");
new ProcessBuilder().command("logcat", "-c").redirectErrorStream(true).start();
Log.i("jrelog-logcat","Starting logcat");
Process p = new ProcessBuilder().command("logcat", /* "-G", "1mb", */ "-v", "brief", "*:S").redirectErrorStream(true).start();
// idk which better, but 512bytes may make a bug that printf(\n) in a single line
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
act.appendlnToLog(line);
}
/*
byte[] buf = new byte[512];
int len;
while ((len = p.getInputStream().read(buf)) != -1) {
appendToLog(new String(buf, 0, len));
}
*/
} catch (IOException e) {
Log.e("jrelog-logcat", "IOException on logging thread");
e.printStackTrace();
act.appendlnToLog("IOException on logging thread:\n" + Log.getStackTraceString(e));
}
});
t.start();
Log.i("jrelog-logcat","Logcat thread started");
}
public static void setJavaEnvironment(Context ctx) throws IOException, ErrnoException { public static void setJavaEnvironment(Context ctx) throws IOException, ErrnoException {
nativeLibDir = ctx.getApplicationInfo().nativeLibraryDir; nativeLibDir = ctx.getApplicationInfo().nativeLibraryDir;
String libName = System.getProperty("os.arch").contains("64") ? "lib64" : "lib"; String libName = System.getProperty("os.arch").contains("64") ? "lib64" : "lib";
@ -77,6 +113,7 @@ public class JREUtils
public static native int chdir(String path); public static native int chdir(String path);
public static native boolean dlopen(String libPath); public static native boolean dlopen(String libPath);
public static native void redirectLogcat();
public static native void setLdLibraryPath(String ldLibraryPath); public static native void setLdLibraryPath(String ldLibraryPath);
public static native void setupBridgeWindow(Object surface); public static native void setupBridgeWindow(Object surface);

View File

@ -0,0 +1,20 @@
package net.kdt.pojavlaunch;
import android.support.v7.app.*;
public abstract class LoggableActivity extends AppCompatActivity
{
public void appendToLog(String text) {
appendToLog(text, true);
}
public void appendlnToLog(String text) {
appendlnToLog(text, true);
}
public void appendlnToLog(String text, boolean checkAllow) {
appendToLog(text + "\n", checkAllow);
}
public abstract void appendToLog(final String text, boolean checkAllow);
}

View File

@ -24,7 +24,7 @@ import org.lwjgl.glfw.*;
import android.app.AlertDialog; import android.app.AlertDialog;
import java.lang.Process; import java.lang.Process;
public class MainActivity extends AppCompatActivity implements OnTouchListener, OnClickListener public class MainActivity extends LoggableActivity implements OnTouchListener, OnClickListener
{ {
public static final String initText = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA "; public static final String initText = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ";
@ -85,7 +85,7 @@ public class MainActivity extends AppCompatActivity implements OnTouchListener,
private NavigationView navDrawer; private NavigationView navDrawer;
private LinearLayout contentLog; private LinearLayout contentLog;
private TextView textLog, textLogBehindGL; private TextView textLog;
private ScrollView contentScroll; private ScrollView contentScroll;
private ToggleButton toggleLog; private ToggleButton toggleLog;
private GestureDetector gestureDetector; private GestureDetector gestureDetector;
@ -103,7 +103,7 @@ public class MainActivity extends AppCompatActivity implements OnTouchListener,
private Button[] controlButtons; private Button[] controlButtons;
private File currLogFile, logFile; private File logFile;
private PrintStream logStream; private PrintStream logStream;
/* /*
@ -238,8 +238,8 @@ public class MainActivity extends AppCompatActivity implements OnTouchListener,
this.textLog = (TextView) contentScroll.getChildAt(0); this.textLog = (TextView) contentScroll.getChildAt(0);
this.toggleLog = (ToggleButton) findViewById(R.id.content_log_toggle_log); this.toggleLog = (ToggleButton) findViewById(R.id.content_log_toggle_log);
this.toggleLog.setChecked(false); this.toggleLog.setChecked(false);
this.textLogBehindGL = (TextView) findViewById(R.id.main_log_behind_GL); // this.textLogBehindGL = (TextView) findViewById(R.id.main_log_behind_GL);
this.textLogBehindGL.setTypeface(Typeface.MONOSPACE); // this.textLogBehindGL.setTypeface(Typeface.MONOSPACE);
this.textLog.setTypeface(Typeface.MONOSPACE); this.textLog.setTypeface(Typeface.MONOSPACE);
this.toggleLog.setOnCheckedChangeListener(new ToggleButton.OnCheckedChangeListener(){ this.toggleLog.setOnCheckedChangeListener(new ToggleButton.OnCheckedChangeListener(){
@ -247,10 +247,6 @@ public class MainActivity extends AppCompatActivity implements OnTouchListener,
@Override @Override
public void onCheckedChanged(CompoundButton button, boolean isChecked) public void onCheckedChanged(CompoundButton button, boolean isChecked)
{ {
try {
if (isChecked) Tools.write(currLogFile.getAbsolutePath(), "");
} catch (Exception e) {}
isLogAllow = isChecked; isLogAllow = isChecked;
appendToLog(""); appendToLog("");
} }
@ -842,7 +838,7 @@ public class MainActivity extends AppCompatActivity implements OnTouchListener,
return Build.VERSION.SDK_INT >= 26; return Build.VERSION.SDK_INT >= 26;
} }
private FileObserver mLogObserver; // private FileObserver mLogObserver;
private void runCraft() throws Throwable { private void runCraft() throws Throwable {
/* Old logger /* Old logger
if (Tools.LAUNCH_TYPE != Tools.LTYPE_PROCESS) { if (Tools.LAUNCH_TYPE != Tools.LTYPE_PROCESS) {
@ -865,25 +861,18 @@ public class MainActivity extends AppCompatActivity implements OnTouchListener,
mLogObserver.startWatching(); mLogObserver.startWatching();
} }
*/ */
JREUtils.redirectLogcat();
Log.v("jrelog","Log starts here"); appendlnToLog("--------- beggining with launcher debug");
Thread t = new Thread(() -> { File lwjgl3dir = new File(Tools.MAIN_PATH, "lwjgl3");
try { if (!lwjgl3dir.exists() || lwjgl3dir.isFile() || lwjgl3dir.length() == 0) {
Log.i("jrelog-logcat","Clearing logcat"); appendlnToLog("Error: LWJGL3 is not installed!");
new ProcessBuilder().command("logcat", "-c").redirectErrorStream(true).start(); Tools.showError(this, new Throwable("LWJGL3 is not installed!"), true);
Log.i("jrelog-logcat","Starting logcat"); return;
Process p = new ProcessBuilder().command("logcat", /* "-G", "1mb", */ "-v", "brief", "*:S").redirectErrorStream(true).start(); } else {
byte[] buf = new byte[512]; appendlnToLog("Info: LWJGL3 directory size: " + lwjgl3dir.length());
int len; }
while ((len = p.getInputStream().read(buf)) != -1) {
appendToLog(new String(buf, 0, len)); JREUtils.redirectAndPrintJRELog(this);
}
}catch (IOException e) {
e.printStackTrace();
}
});
t.start();
Log.i("jrelog-logcat","Logcat thread started");
Tools.launchMinecraft(this, mProfile, mVersionInfo); Tools.launchMinecraft(this, mProfile, mVersionInfo);
} }
@ -942,19 +931,9 @@ public class MainActivity extends AppCompatActivity implements OnTouchListener,
WindowAnimation.fadeOut(contentCanvas, 500); WindowAnimation.fadeOut(contentCanvas, 500);
} }
*/ */
private void appendToLog(String text) {
appendToLog(text, true); @Override
} public void appendToLog(final String text, boolean checkAllow) {
private void appendlnToLog(String text) {
appendlnToLog(text, true);
}
private void appendlnToLog(String text, boolean checkAllow) {
appendToLog(text + "\n", checkAllow);
}
private void appendToLog(final String text, boolean checkAllow) {
logStream.print(text); logStream.print(text);
if (checkAllow && !isLogAllow) return; if (checkAllow && !isLogAllow) return;
textLog.post(new Runnable(){ textLog.post(new Runnable(){

View File

@ -81,35 +81,6 @@ public final class Tools
*/ */
javaArgList.add(Tools.homeJreDir + "/bin/java"); javaArgList.add(Tools.homeJreDir + "/bin/java");
List<String> overrideableArgList = new ArrayList<String>();
overrideableArgList.add("-Djava.home=" + Tools.homeJreDir);
overrideableArgList.add("-Djava.io.tmpdir=" + ctx.getCacheDir().getAbsolutePath());
overrideableArgList.add("-Dos.name=Linux");
// javaArgList.add("-Dorg.lwjgl.libname=liblwjgl3.so");
// javaArgList.add("-Dorg.lwjgl.system.jemalloc.libname=libjemalloc.so");
overrideableArgList.add("-Dorg.lwjgl.opengl.libname=libgl04es.so");
// javaArgList.add("-Dorg.lwjgl.opengl.libname=libRegal.so");
// Enable LWJGL3 debug
overrideableArgList.add("-Dorg.lwjgl.util.Debug=true");
// overrideableArgList.add("-Dorg.lwjgl.util.DebugFunctions=true");
overrideableArgList.add("-Dorg.lwjgl.util.DebugLoader=true");
// GLFW Stub width height
overrideableArgList.add("-Dglfwstub.windowWidth=" + CallbackBridge.windowWidth);
overrideableArgList.add("-Dglfwstub.windowHeight=" + CallbackBridge.windowHeight);
overrideableArgList.add("-Dglfwstub.initEgl=false");
if (versionInfo.arguments != null) {
// Minecraft 1.13+
overrideableArgList.add("-Dminecraft.launcher.brand=" + Tools.APP_NAME);
overrideableArgList.add("-Dminecraft.launcher.version=" + ctx.getPackageManager().getPackageInfo(ctx.getPackageName(), 0).versionName);
}
String launchClassPath = generateLaunchClassPath(profile.getVersion()); String launchClassPath = generateLaunchClassPath(profile.getVersion());
System.out.println("Java Classpath: " + launchClassPath); System.out.println("Java Classpath: " + launchClassPath);
if (LAUNCH_TYPE == LTYPE_CREATEJAVAVM) { if (LAUNCH_TYPE == LTYPE_CREATEJAVAVM) {
@ -128,21 +99,8 @@ public final class Tools
javaArgList.add("-Dglfwstub.eglSurfaceDraw=" + Tools.getEGLAddress("Surface", AndroidContextImplementation.draw)); javaArgList.add("-Dglfwstub.eglSurfaceDraw=" + Tools.getEGLAddress("Surface", AndroidContextImplementation.draw));
} }
*/ */
// Override args
// TODO fix duplicate args
for (String argOverride : LauncherPreferences.PREF_CUSTOM_JAVA_ARGS.split(" ")) {
for (int i = 0; i < overrideableArgList.size(); i++) {
String arg = overrideableArgList.get(i);
if (arg.startsWith("-D") && argOverride.startsWith(arg.substring(0, arg.indexOf('=') + 1))) {
overrideableArgList.set(i, argOverride);
break;
} else if (i+1 == overrideableArgList.size()) {
javaArgList.add(argOverride);
}
}
}
javaArgList.addAll(overrideableArgList); getJavaArgs(ctx, javaArgList);
javaArgList.add("-cp"); javaArgList.add("-cp");
javaArgList.add(launchClassPath); javaArgList.add(launchClassPath);
@ -218,7 +176,49 @@ public final class Tools
} }
}); });
} }
public static void getJavaArgs(Context ctx, List<String> javaArgList) {
List<String> overrideableArgList = new ArrayList<String>();
overrideableArgList.add("-Djava.home=" + Tools.homeJreDir);
overrideableArgList.add("-Djava.io.tmpdir=" + ctx.getCacheDir().getAbsolutePath());
// Should be compatible?
overrideableArgList.add("-Dos.name=Android");
overrideableArgList.add("-Dos.version=" + Build.VERSION.SDK);
// javaArgList.add("-Dorg.lwjgl.libname=liblwjgl3.so");
// javaArgList.add("-Dorg.lwjgl.system.jemalloc.libname=libjemalloc.so");
overrideableArgList.add("-Dorg.lwjgl.opengl.libname=libgl04es.so");
// javaArgList.add("-Dorg.lwjgl.opengl.libname=libRegal.so");
// Enable LWJGL3 debug
overrideableArgList.add("-Dorg.lwjgl.util.Debug=true");
// overrideableArgList.add("-Dorg.lwjgl.util.DebugFunctions=true");
overrideableArgList.add("-Dorg.lwjgl.util.DebugLoader=true");
// GLFW Stub width height
overrideableArgList.add("-Dglfwstub.windowWidth=" + CallbackBridge.windowWidth);
overrideableArgList.add("-Dglfwstub.windowHeight=" + CallbackBridge.windowHeight);
overrideableArgList.add("-Dglfwstub.initEgl=false");
// Override args
for (String argOverride : LauncherPreferences.PREF_CUSTOM_JAVA_ARGS.split(" ")) {
for (int i = 0; i < overrideableArgList.size(); i++) {
String arg = overrideableArgList.get(i);
if (arg.startsWith("-D") && argOverride.startsWith(arg.substring(0, arg.indexOf('=') + 1))) {
overrideableArgList.set(i, argOverride);
break;
} else if (i+1 == overrideableArgList.size()) {
javaArgList.add(argOverride);
}
}
}
javaArgList.addAll(overrideableArgList);
}
public static String[] getMinecraftArgs(MCProfile.Builder profile, JMinecraftVersionList.Version versionInfo) public static String[] getMinecraftArgs(MCProfile.Builder profile, JMinecraftVersionList.Version versionInfo)
{ {
String username = profile.getUsername(); String username = profile.getUsername();

View File

@ -1,21 +1,89 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout <FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_width="match_parent"> android:layout_width="match_parent">
<TextureView <RelativeLayout
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_width="match_parent" android:layout_width="match_parent">
android:id="@+id/installmod_surfaceview"/>
<Button <TextureView
android:layout_height="wrap_content" android:layout_height="match_parent"
android:layout_width="match_parent"
android:id="@+id/installmod_surfaceview"/>
<Button
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:background="@drawable/control_button"
android:layout_alignParentRight="true"
android:text="@string/control_forceclose"
android:onClick="forceClose"
android:id="@+id/installmod_btn2"/>
<Button
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:background="@drawable/control_button"
android:text="@string/control_viewout"
android:onClick="openLogOutput"
android:layout_toLeftOf="@id/installmod_btn2"/>
</RelativeLayout>
<LinearLayout
android:id="@+id/content_log_layout"
android:layout_height="match_parent"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:background="@drawable/control_button" android:visibility="gone"
android:layout_alignParentRight="true" android:orientation="vertical">
android:text="@string/control_forceclose"
android:onClick="forceClose"/>
</RelativeLayout> <RelativeLayout
android:layout_height="84px"
android:layout_width="match_parent"
android:gravity="center_vertical"
android:background="#555555">
<TextView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="@string/control_viewout"
android:paddingLeft="30px"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_centerVertical="true"/>
<ImageView
android:layout_height="84px"
android:layout_width="84px"
android:src="@android:drawable/ic_delete"
android:onClick="closeLogOutput"
android:layout_alignParentRight="true"
android:id="@+id/content_log_close_button"/>
<ToggleButton
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_toLeftOf="@id/content_log_close_button"
android:id="@+id/content_log_toggle_log"/>
</RelativeLayout>
<ScrollView
android:layout_height="match_parent"
android:layout_width="match_parent"
android:id="@+id/content_log_scroll"
android:alpha="0.8"
android:background="#000000">
<TextView
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:textIsSelectable="true"/>
</ScrollView>
</LinearLayout>
</FrameLayout>