API rewrite: high level APIs

This commit is contained in:
topjohnwu 2018-07-22 15:32:51 +08:00
parent 6947a968cb
commit 5f9adec47e
3 changed files with 138 additions and 56 deletions

View File

@ -22,7 +22,7 @@ public class MainActivity extends Activity {
private TextView console;
private EditText input;
private ScrollView sv;
private List<String> consoleList;
private Shell.Output output;
@Override
protected void onCreate(Bundle savedInstanceState) {
@ -43,7 +43,7 @@ public class MainActivity extends Activity {
sync_cmd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Shell.Sync.sh(consoleList, input.getText().toString());
Shell.sh(input.getText().toString()).to(output).exec();
input.setText("");
}
});
@ -53,20 +53,14 @@ public class MainActivity extends Activity {
async_cmd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Shell.Async.sh(consoleList, consoleList,
new Shell.Async.Callback() {
Shell.sh(input.getText().toString())
.to(output)
.onResult(new Shell.ResultCallback() {
@Override
public void onTaskResult(List<String> out, List<String> err) {
Log.d(ExampleApp.TAG, "in_async_callback");
public void onResult(Shell.Output out) {
Log.d(ExampleApp.TAG, "async_cmd_result");
}
@Override
public void onTaskError(Throwable err) {
Log.d(ExampleApp.TAG, "async_callback_error");
err.printStackTrace();
}
},
input.getText().toString());
}).enqueue();
input.setText("");
}
});
@ -87,7 +81,7 @@ public class MainActivity extends Activity {
sync_script.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Shell.Sync.loadScript(consoleList, getResources().openRawResource(R.raw.info));
Shell.sh(getResources().openRawResource(R.raw.info)).to(output).exec();
}
});
@ -95,23 +89,30 @@ public class MainActivity extends Activity {
async_script.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Shell.Async.loadScript(consoleList, getResources().openRawResource(R.raw.count));
Shell.sh(getResources().openRawResource(R.raw.count))
.to(output)
.onResult(new Shell.ResultCallback() {
@Override
public void onResult(Shell.Output out) {
Log.d(ExampleApp.TAG, "async_script_result");
}
}).enqueue();
}
});
clear.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
consoleList.clear();
output.getOut().clear();
}
});
/* Create a CallbackList to update the UI with Shell output
* Here I demonstrate 2 ways to implement a CallbackList
* Use either ContainerCallbackList or StringBuilderCallbackList
* Both implementation has the same result
* Both implementation will have the same result
*/
consoleList = new ContainerCallbackList(new ArrayList<String>());
output = new Shell.Output(new ContainerCallbackList(new ArrayList<String>()));
}
private class ContainerCallbackList extends CallbackList<String> {

View File

@ -25,6 +25,7 @@ import android.support.annotation.Nullable;
import com.topjohnwu.superuser.internal.DeprecatedApiShim;
import com.topjohnwu.superuser.internal.Factory;
import com.topjohnwu.superuser.internal.InternalUtils;
import com.topjohnwu.superuser.internal.NOPJob;
import java.io.Closeable;
import java.io.IOException;
@ -32,6 +33,7 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.lang.ref.WeakReference;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.List;
/**
@ -404,6 +406,77 @@ public abstract class Shell implements Closeable {
}
}
/* ************
* Static APIs
* ************/
public static Job su(String... commands) {
Shell shell = getShell();
if (shell.isRoot())
return sh(commands);
return new NOPJob();
}
public static Job sh(String... commands) {
return newJob(getShell(), commands);
}
public static Job su(InputStream in) {
Shell shell = getShell();
if (shell.isRoot())
return sh(in);
return new NOPJob();
}
public static Job sh(InputStream in) {
return newJob(getShell(), in);
}
/* **********************
* Private helper methods
* ***********************/
private static Job newJob(Shell shell, String... commands) {
return shell.newJob(commands).to(new Output(new ArrayList<>()));
}
private static Job newJob(Shell shell, InputStream in) {
return shell.newJob(in).to(new Output(new ArrayList<>()));
}
private static void initShell(Shell shell) {
Initializer init = null;
if (initClass != null) {
try {
// Force enabling the default constructor as it might be private
Constructor<? extends Initializer> ic = initClass.getDeclaredConstructor();
ic.setAccessible(true);
init = ic.newInstance();
} catch (Exception e) {
InternalUtils.stackTrace(e);
}
} else if (initializer != null) {
init = initializer;
}
if (init == null)
init = new Initializer();
if (!init.init(shell))
throw new NoShellException();
}
private static Shell getGlobalShell() {
Shell shell = null;
Container container = weakContainer.get();
if (container != null)
shell = container.getShell();
if (shell != null && !shell.isAlive())
shell = null;
return shell;
}
/* ***************
* Non-static APIs
* ****************/
@ -441,43 +514,6 @@ public abstract class Shell implements Closeable {
return status >= ROOT_SHELL;
}
/* **********************
* Private helper methods
* ***********************/
private static void initShell(Shell shell) {
Initializer init = null;
if (initClass != null) {
try {
// Force enabling the default constructor as it might be private
Constructor<? extends Initializer> ic = initClass.getDeclaredConstructor();
ic.setAccessible(true);
init = ic.newInstance();
} catch (Exception e) {
InternalUtils.stackTrace(e);
}
} else if (initializer != null) {
init = initializer;
}
if (init == null)
init = new Initializer();
if (!init.init(shell))
throw new NoShellException();
}
private static Shell getGlobalShell() {
Shell shell = null;
Container container = weakContainer.get();
if (container != null)
shell = container.getShell();
if (shell != null && !shell.isAlive())
shell = null;
return shell;
}
/* **********
* Subclasses
* ***********/

View File

@ -0,0 +1,45 @@
/*
* Copyright 2018 John "topjohnwu" Wu
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.topjohnwu.superuser.internal;
import com.topjohnwu.superuser.Shell;
public class NOPJob extends Shell.Job {
private Shell.ResultCallback cb;
@Override
public Shell.Job to(Shell.Output out) {
return this;
}
@Override
public Shell.Job onResult(Shell.ResultCallback cb) {
this.cb = cb;
return this;
}
@Override
public Shell.Output exec() {
return new Shell.Output(null, null);
}
@Override
public void enqueue() {
cb.onResult(exec());
}
}