Finalize APIs

This commit is contained in:
topjohnwu 2018-01-25 17:27:48 +08:00
parent 9811c009cb
commit d9bcf78bc8
12 changed files with 748 additions and 327 deletions

View File

@ -8,7 +8,6 @@ buildscript {
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.0.1' classpath 'com.android.tools.build:gradle:3.0.1'
classpath 'com.github.dcendents:android-maven-gradle-plugin:2.0'
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong

View File

@ -1,39 +1,12 @@
package com.topjohnwu.libsuexample; package com.topjohnwu.libsuexample;
import android.app.Application;
import com.topjohnwu.superuser.Shell; import com.topjohnwu.superuser.Shell;
import com.topjohnwu.superuser.ShellContainer;
/** public class ExampleApp extends Shell.ContainerApp {
* The {@link Application} of the Example app.
* <p>
* We implement {@link ShellContainer} to the {@link Application} of
* the app, which means that we would love our root shell to live as long as the
* application itself.
*/
public class ExampleApp extends Application implements ShellContainer {
/** public ExampleApp() {
* A shell instance living alongside the lifecycle of {@link ExampleApp} // Set flags
*/ Shell.setFlags(Shell.FLAG_REDIRECT_STDERR);
public Shell mShell; Shell.verboseLogging(BuildConfig.DEBUG);
@Override
public void onCreate() {
super.onCreate();
// Enable verbose logging flags
Shell.addFlags(Shell.FLAG_VERBOSE_LOGGING | Shell.FLAG_REDIRECT_STDERR);
Shell.setGlobalContainer(this);
}
@Override
public Shell getShell() {
return mShell;
}
@Override
public void setShell(Shell shell) {
mShell = shell;
} }
} }

View File

@ -2,15 +2,16 @@ package com.topjohnwu.libsuexample;
import android.app.Activity; import android.app.Activity;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log;
import android.widget.Button; import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ScrollView; import android.widget.ScrollView;
import android.widget.TextView; import android.widget.TextView;
import com.topjohnwu.superuser.CallbackList; import com.topjohnwu.superuser.CallbackList;
import com.topjohnwu.superuser.NoShellException;
import com.topjohnwu.superuser.Shell; import com.topjohnwu.superuser.Shell;
import java.io.IOException;
import java.util.List; import java.util.List;
public class MainActivity extends Activity { public class MainActivity extends Activity {
@ -20,7 +21,7 @@ public class MainActivity extends Activity {
private TextView console; private TextView console;
private EditText input; private EditText input;
private ScrollView sv; private ScrollView sv;
private List<String> callback; private List<String> consoleList;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
@ -32,57 +33,51 @@ public class MainActivity extends Activity {
Button sync_cmd = findViewById(R.id.sync_cmd); Button sync_cmd = findViewById(R.id.sync_cmd);
Button async_cmd = findViewById(R.id.async_cmd); Button async_cmd = findViewById(R.id.async_cmd);
Button raw_cmd = findViewById(R.id.raw_cmd); Button close_shell = findViewById(R.id.close_shell);
Button sync_script = findViewById(R.id.sync_script); Button sync_script = findViewById(R.id.sync_script);
Button async_script = findViewById(R.id.async_script); Button async_script = findViewById(R.id.async_script);
Button clear = findViewById(R.id.clear); Button clear = findViewById(R.id.clear);
// Run the shell command in the input box synchronously // Run the shell command in the input box synchronously
sync_cmd.setOnClickListener(v -> { sync_cmd.setOnClickListener(v -> {
Shell.su(callback, input.getText().toString()); Shell.Sync.su(consoleList, input.getText().toString());
input.setText(""); input.setText("");
}); });
// Run the shell command in the input box asynchronously // Run the shell command in the input box asynchronously.
// Also demonstrates that Async.Callback works
async_cmd.setOnClickListener(v -> { async_cmd.setOnClickListener(v -> {
Shell.su_async(callback, input.getText().toString()); Shell.Async.su(consoleList, consoleList,
(out, err) -> Log.d(TAG, "in_async_callback"),
input.getText().toString());
input.setText(""); input.setText("");
}); });
// Run the shell command in the input box ignoring output asynchronously // Closing a shell is always synchronous
raw_cmd.setOnClickListener(v -> { close_shell.setOnClickListener(v -> {
Shell.su_raw(input.getText().toString());
input.setText("");
});
// Load a script from raw resources
sync_script.setOnClickListener(v -> {
try { try {
Shell.getShell().loadInputStream(callback, callback, Shell.getShell().close();
getResources().openRawResource(R.raw.info)); } catch (IOException e) {
} catch (NoShellException e) {
e.printStackTrace(); e.printStackTrace();
} }
}); });
// Load a script from raw resources // Load a script from raw resources synchronously
async_script.setOnClickListener(v -> { sync_script.setOnClickListener(v ->
try { Shell.Sync.loadScript(consoleList,
Shell.getShell().loadInputStreamAsync(callback, callback, getResources().openRawResource(R.raw.info)));
getResources().openRawResource(R.raw.count));
} catch (NoShellException e) {
e.printStackTrace();
}
});
clear.setOnClickListener(v -> { // Load a script from raw resources asynchronously
callback.clear(); async_script.setOnClickListener(v ->
console.setText(""); Shell.Async.loadScript(consoleList,
}); getResources().openRawResource(R.raw.count))
);
// We create a ShellCallback to update the UI with the Shell output clear.setOnClickListener(v -> consoleList.clear());
callback = new CallbackList<String>() {
StringBuilder builder = new StringBuilder(); // We create a CallbackList to update the UI with the Shell output
consoleList = new CallbackList<String>() {
private StringBuilder builder = new StringBuilder();
@Override @Override
public void onAddElement(String s) { public void onAddElement(String s) {
@ -94,6 +89,7 @@ public class MainActivity extends Activity {
@Override @Override
public void clear() { public void clear() {
builder = new StringBuilder(); builder = new StringBuilder();
handler.post(() -> console.setText(""));
} }
}; };
} }

View File

@ -63,12 +63,12 @@
android:text="Async CMD" /> android:text="Async CMD" />
<Button <Button
android:id="@+id/raw_cmd" android:id="@+id/close_shell"
style="?android:borderlessButtonStyle" style="?android:borderlessButtonStyle"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:text="Raw CMD" /> android:text="Close Shell" />
</LinearLayout> </LinearLayout>

View File

@ -18,8 +18,6 @@ android {
defaultConfig { defaultConfig {
minSdkVersion 14 minSdkVersion 14
targetSdkVersion 27 targetSdkVersion 27
versionCode 10
versionName "0.1.0"
} }
buildTypes { buildTypes {
@ -32,6 +30,7 @@ android {
task javadoc(type: Javadoc) { task javadoc(type: Javadoc) {
failOnError false failOnError false
title = 'libsu API'
source = android.sourceSets.main.java.sourceFiles source = android.sourceSets.main.java.sourceFiles
classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
classpath += configurations.compile classpath += configurations.compile
@ -42,4 +41,5 @@ task javadoc(type: Javadoc) {
dependencies { dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar']) implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:support-annotations:27.0.2'
} }

View File

@ -26,8 +26,13 @@ import java.util.List;
public abstract class CallbackList<E> extends AbstractList<E> { public abstract class CallbackList<E> extends AbstractList<E> {
private Handler handler = null; /**
private List<E> mBase = null; * The internal handler to run the callback on the main thread.
* It will only get created when the constructor is called on the main thread.
*/
protected Handler handler = null;
protected List<E> mBase = null;
/** /**
* Sole constructor. Will setup a {@link Handler} if constructed in the main thread. * Sole constructor. Will setup a {@link Handler} if constructed in the main thread.

View File

@ -1,12 +1,13 @@
package com.topjohnwu.superuser; package com.topjohnwu.superuser;
/** /**
* Created by topjohnwu on 2018/1/19. * Thrown when it is impossible to construct {@code Shell}.
* This is a runtime exception, and should happen very rarely.
*/ */
public class NoShellException extends Exception { public class NoShellException extends RuntimeException {
public NoShellException() { public NoShellException() {
super("Unable to start a shell!"); super("Impossible to create a shell!");
} }
} }

View File

@ -1,67 +0,0 @@
package com.topjohnwu.superuser;
import android.os.AsyncTask;
/**
* Created by topjohnwu on 2018/1/22.
*/
public abstract class PoolThread {
private static final int NOT_STARTED = 0;
private static final int RUNNING = 1;
private static final int DONE = 2;
private int status;
PoolThread() {
status = NOT_STARTED;
}
abstract void run();
PoolThread start() {
AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
@Override
public void run() {
notifyRunning();
PoolThread.this.run();
notifyDone();
}
});
return this;
}
synchronized void waitTillStart() {
while (status == NOT_STARTED) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void join() throws InterruptedException {
join(0, 0);
}
public void join(long millis) throws InterruptedException {
join(millis, 0);
}
public synchronized void join(long millis, int nanos) throws InterruptedException {
while (status != DONE)
wait(millis, nanos);
}
private synchronized void notifyRunning() {
status = RUNNING;
notifyAll();
}
private synchronized void notifyDone() {
status = DONE;
notifyAll();
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +0,0 @@
package com.topjohnwu.superuser;
/**
* Created by topjohnwu on 2018/1/19.
*/
public interface ShellContainer {
Shell getShell();
void setShell(Shell shell);
}

View File

@ -1,10 +0,0 @@
package com.topjohnwu.superuser;
/**
* Created by topjohnwu on 2018/1/21.
*/
public class ShellInitializer {
public void onShellInit(Shell shell) {}
public void onRootShellInit(Shell shell) {}
}

View File

@ -9,10 +9,6 @@ import java.io.InputStreamReader;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
/**
* Created by topjohnwu on 2018/1/19.
*/
class StreamGobbler extends Thread { class StreamGobbler extends Thread {
private static final String TAG = "SHELLOUT"; private static final String TAG = "SHELLOUT";