mirror of
https://github.com/topjohnwu/libsu.git
synced 2024-10-07 17:23:29 +00:00
Finalize APIs
This commit is contained in:
parent
9811c009cb
commit
d9bcf78bc8
@ -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
|
||||||
|
@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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(""));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
|
|
||||||
|
@ -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'
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
|
@ -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!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
@ -1,10 +0,0 @@
|
|||||||
package com.topjohnwu.superuser;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by topjohnwu on 2018/1/19.
|
|
||||||
*/
|
|
||||||
|
|
||||||
public interface ShellContainer {
|
|
||||||
Shell getShell();
|
|
||||||
void setShell(Shell shell);
|
|
||||||
}
|
|
@ -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) {}
|
|
||||||
}
|
|
@ -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";
|
||||||
|
Loading…
Reference in New Issue
Block a user