mirror of
https://github.com/playmusicexporter/playmusicexporter
synced 2024-05-02 11:26:43 +00:00
#29: Remove superuser module and import it from the new repo
This commit is contained in:
parent
aa42259163
commit
7211eaf2cf
|
@ -10,7 +10,6 @@
|
|||
<option value="$PROJECT_DIR$" />
|
||||
<option value="$PROJECT_DIR$/playmusicexporter" />
|
||||
<option value="$PROJECT_DIR$/playmusiclib" />
|
||||
<option value="$PROJECT_DIR$/superuser" />
|
||||
</set>
|
||||
</option>
|
||||
<option name="resolveModulePerSourceSet" value="false" />
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
<module fileurl="file://$PROJECT_DIR$/PlayMusicExporter.iml" filepath="$PROJECT_DIR$/PlayMusicExporter.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/playmusicexporter/playmusicexporter.iml" filepath="$PROJECT_DIR$/playmusicexporter/playmusicexporter.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/playmusiclib/playmusiclib.iml" filepath="$PROJECT_DIR$/playmusiclib/playmusiclib.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/superuser/superuser.iml" filepath="$PROJECT_DIR$/superuser/superuser.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
|
@ -25,6 +25,7 @@
|
|||
buildscript {
|
||||
repositories {
|
||||
jcenter()
|
||||
google()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.0.0-beta2'
|
||||
|
@ -35,11 +36,7 @@ buildscript {
|
|||
allprojects {
|
||||
repositories {
|
||||
jcenter()
|
||||
maven {
|
||||
url 'https://maven.google.com'
|
||||
}
|
||||
maven {
|
||||
url 'https://jitpack.io'
|
||||
}
|
||||
google()
|
||||
maven { url 'https://jitpack.io' }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,9 +50,8 @@ android {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||
compile project(':superuser')
|
||||
compile project(':playmusiclib')
|
||||
compile 'com.github.playmusicexporter:superuserlib:v1.0.0'
|
||||
compile 'com.android.support:appcompat-v7:26.0.1'
|
||||
compile 'com.android.support:support-v13:26.0.1'
|
||||
compile 'com.android.support:design:26.0.1'
|
||||
|
@ -63,4 +62,4 @@ dependencies {
|
|||
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5.1'
|
||||
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.1'
|
||||
testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.1'
|
||||
}
|
||||
}
|
|
@ -18,7 +18,7 @@ import com.github.paolorotolo.appintro.AppIntroFragment;
|
|||
|
||||
import java.util.Optional;
|
||||
|
||||
import rc.jcg.superuser.SuperUser;
|
||||
import re.jcg.superuser.SuperUser;
|
||||
import re.jcg.playmusicexporter.R;
|
||||
import re.jcg.playmusicexporter.settings.PlayMusicExporterPreferences;
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ android {
|
|||
buildToolsVersion '26.0.1'
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 14
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 26
|
||||
versionCode 1
|
||||
versionName '1.0'
|
||||
|
@ -45,6 +45,7 @@ android {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
compile project(':superuser')
|
||||
compile 'com.github.playmusicexporter:superuserlib:v1.0.0'
|
||||
compile 'com.android.support:appcompat-v7:26.0.1'
|
||||
compile 'com.mpatric:mp3agic:0.9.0'
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ import android.text.TextUtils;
|
|||
|
||||
import java.net.URL;
|
||||
|
||||
import rc.jcg.superuser.SuperUserTools;
|
||||
import re.jcg.superuser.SuperUserTools;
|
||||
import de.arcus.playmusiclib.utils.ImageTools;
|
||||
import de.arcus.playmusiclib.items.ArtworkEntry;
|
||||
|
||||
|
|
|
@ -56,8 +56,8 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import rc.jcg.superuser.SuperUser;
|
||||
import rc.jcg.superuser.SuperUserTools;
|
||||
import re.jcg.superuser.SuperUser;
|
||||
import re.jcg.superuser.SuperUserTools;
|
||||
import de.arcus.playmusiclib.utils.FileTools;
|
||||
import de.arcus.playmusiclib.enums.ID3v2Version;
|
||||
import de.arcus.playmusiclib.exceptions.CouldNotOpenDatabaseException;
|
||||
|
|
|
@ -22,4 +22,4 @@
|
|||
|
||||
|
||||
|
||||
include ':playmusicexporter', ':superuser', ':playmusiclib'
|
||||
include ':playmusicexporter', ':playmusiclib'
|
||||
|
|
|
@ -1,50 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2015 David Schulte
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
compileSdkVersion 26
|
||||
buildToolsVersion '26.0.1'
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 14
|
||||
targetSdkVersion 26
|
||||
versionCode 1
|
||||
versionName '1.0'
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled true
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
targetCompatibility 1.8
|
||||
sourceCompatibility 1.8
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||
compile 'com.android.support:appcompat-v7:26.0.1'
|
||||
}
|
17
superuser/proguard-rules.pro
vendored
17
superuser/proguard-rules.pro
vendored
|
@ -1,17 +0,0 @@
|
|||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in /home/david/android-sdks/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the proguardFiles
|
||||
# directive in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
|
@ -1,25 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (c) 2015 David Schulte
|
||||
~
|
||||
~ Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
~ of this software and associated documentation files (the "Software"), to deal
|
||||
~ in the Software without restriction, including without limitation the rights
|
||||
~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
~ copies of the Software, and to permit persons to whom the Software is
|
||||
~ furnished to do so, subject to the following conditions:
|
||||
~
|
||||
~ The above copyright notice and this permission notice shall be included in
|
||||
~ all copies or substantial portions of the Software.
|
||||
~
|
||||
~ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
~ THE SOFTWARE.
|
||||
-->
|
||||
|
||||
<manifest package="re.icg.superuser">
|
||||
</manifest>
|
|
@ -1,129 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2015 David Schulte
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package rc.jcg.superuser;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A dynamic growing byte buffer
|
||||
*/
|
||||
public class ByteBuffer {
|
||||
private int mChunkSize = 4096;
|
||||
private int mSize = 0;
|
||||
private List<byte[]> mChunks = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Creates a byte buffer
|
||||
*/
|
||||
public ByteBuffer() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a byte buffer
|
||||
* @param chunkSize Sets the chunks size
|
||||
*/
|
||||
public ByteBuffer(int chunkSize) {
|
||||
mChunkSize = chunkSize;
|
||||
}
|
||||
/**
|
||||
* @return Returns the size of the buffer
|
||||
*/
|
||||
public long size() {
|
||||
return mSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the buffer
|
||||
*/
|
||||
public void clear() {
|
||||
mSize = 0;
|
||||
mChunks.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds bytes to the buffer
|
||||
* @param bytes The bytes to add
|
||||
*/
|
||||
public void append(byte[] bytes, int offset, int length) {
|
||||
|
||||
|
||||
while(length > 0) {
|
||||
int freeSpaceInEndChunk = mChunks.size() * mChunkSize - mSize;
|
||||
int positionInEndChunk = mChunkSize - freeSpaceInEndChunk;
|
||||
|
||||
// Adds a new chunk
|
||||
if (freeSpaceInEndChunk == 0) {
|
||||
mChunks.add(new byte[mChunkSize]);
|
||||
freeSpaceInEndChunk = mChunkSize;
|
||||
positionInEndChunk = 0;
|
||||
}
|
||||
byte[] endChunk = mChunks.get(mChunks.size() - 1);
|
||||
|
||||
// We want to add more bytes the chunk can contain
|
||||
if (length > freeSpaceInEndChunk) {
|
||||
|
||||
// Copies to end of chunk
|
||||
System.arraycopy(bytes, offset, endChunk, positionInEndChunk, freeSpaceInEndChunk);
|
||||
|
||||
// Adds the size
|
||||
mSize += freeSpaceInEndChunk;
|
||||
offset += freeSpaceInEndChunk;
|
||||
length -= freeSpaceInEndChunk;
|
||||
} else {
|
||||
// Copies the rest of the data
|
||||
System.arraycopy(bytes, offset, endChunk, positionInEndChunk, length);
|
||||
|
||||
// Adds the size
|
||||
mSize += length;
|
||||
|
||||
offset += length;
|
||||
length = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the bytes as array
|
||||
*/
|
||||
public byte[] toByteArray() {
|
||||
byte[] bytes = new byte[mSize];
|
||||
|
||||
int pos = 0;
|
||||
|
||||
// Copies all chunks
|
||||
for(byte[] subBytes : mChunks) {
|
||||
int chunkSize = mChunkSize;
|
||||
// Last segment
|
||||
if (pos + chunkSize > mSize)
|
||||
chunkSize = mSize - pos;
|
||||
|
||||
// Copies the bytes
|
||||
System.arraycopy(subBytes, 0, bytes, pos, chunkSize);
|
||||
|
||||
pos += chunkSize;
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
}
|
|
@ -1,148 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2015 David Schulte
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package rc.jcg.superuser;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* The superuser managers
|
||||
*
|
||||
* This static class handles the superuser session.
|
||||
* Start the session with {@link #askForPermissions() askForPermissions}.
|
||||
* To run a command create an instance of {@link SuperUserCommand SuperUserCommand} and {@link SuperUserCommand#execute() execute} it.
|
||||
*/
|
||||
public class SuperUser {
|
||||
/**
|
||||
* The su process
|
||||
*/
|
||||
private static Process mProcess;
|
||||
|
||||
/**
|
||||
* Gets the active su process
|
||||
* @return Process
|
||||
*/
|
||||
static Process getProcess() {
|
||||
return mProcess;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the superuser session
|
||||
* To start the session in your app use {@link #askForPermissions()}
|
||||
*/
|
||||
private static boolean sessionStart() {
|
||||
// Starts the su process
|
||||
try {
|
||||
mProcess = Runtime.getRuntime().exec("su");
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the superuser session
|
||||
*/
|
||||
public static void sessionStop() {
|
||||
if (mProcess == null) return;
|
||||
|
||||
// End the process
|
||||
mProcess.destroy();
|
||||
mProcess = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether the su session is running
|
||||
* @return Return whether the su session is running
|
||||
*/
|
||||
public static boolean sessionIsRunning() {
|
||||
if (mProcess == null) return false;
|
||||
|
||||
// Hack to see if the process is running
|
||||
// This is not nice, but there is no other way to check this
|
||||
try {
|
||||
mProcess.exitValue();
|
||||
return false;
|
||||
} catch(IllegalThreadStateException ex) {
|
||||
// Could not get the return value => process is running
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether superuser permissions were granted
|
||||
* @return Return whether superuser permissions were granted
|
||||
*/
|
||||
public static boolean hasPermissions() {
|
||||
// Just check whether the session is running
|
||||
return sessionIsRunning();
|
||||
}
|
||||
|
||||
/**
|
||||
* This is like hasPermissions() but asks for the superuser permissions
|
||||
* and give the user a change to grant it now.
|
||||
* Use this to start you session
|
||||
* @return Return whether superuser permissions were granted
|
||||
*/
|
||||
public static boolean askForPermissions() {
|
||||
// We already have superuser permissions
|
||||
if (hasPermissions()) return true;
|
||||
|
||||
// Starts the process
|
||||
if (sessionStart()) {
|
||||
// Test for superuser
|
||||
SuperUserCommand superUserCommand = new SuperUserCommand("echo 'root'");
|
||||
|
||||
if (superUserCommand.execute()) {
|
||||
// Gets the whoami username
|
||||
String[] output = superUserCommand.getStandardOutput();
|
||||
if (output.length >= 1 && output[0].equals("root")) {
|
||||
// We are root
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We don't have superuser permissions; abort session
|
||||
sessionStop();
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void askForPermissionInBackground(final SuperUserPermissionRequestListener listener) {
|
||||
new AsyncTask<Void, Void, Void>() {
|
||||
boolean hasPermissions;
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
hasPermissions = askForPermissions();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Void result) {
|
||||
listener.superUserGranted(hasPermissions);
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
}
|
|
@ -1,383 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2015 David Schulte
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package rc.jcg.superuser;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This class executes superuser commands.
|
||||
*/
|
||||
public class SuperUserCommand {
|
||||
/**
|
||||
* The default timeout for each command in milliseconds
|
||||
*/
|
||||
private static final long DEFAULT_COMMAND_TIMEOUT = 30 * 1000; // 30 seconds
|
||||
|
||||
private String[] mCommands = new String[] {};
|
||||
private String[] mOutputStandard = new String[] {};
|
||||
private String[] mOutputError = new String[] {};
|
||||
|
||||
// If we want to get a binary return
|
||||
private byte[] mOutputStandardBinary = new byte[] {};
|
||||
|
||||
/**
|
||||
* Command failed?
|
||||
*/
|
||||
private boolean mSuperUserFailed;
|
||||
|
||||
/**
|
||||
* If this value is set, the command will not store any input to the logger
|
||||
*/
|
||||
private boolean mHideInput = false;
|
||||
/**
|
||||
* If this value is set, the command will not store any standard output to the logger
|
||||
*/
|
||||
private boolean mHideStandardOutput = false;
|
||||
/**
|
||||
* If this value is set, the command will not store any error output to the logger
|
||||
*/
|
||||
private boolean mHideErrorOutput = false;
|
||||
|
||||
/**
|
||||
* @return Gets whether the command hides the input log
|
||||
*/
|
||||
public boolean getHideInput() {
|
||||
return mHideInput;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param hideInput Set this to hide the input to the logger
|
||||
*/
|
||||
public void setHideInput(boolean hideInput) {
|
||||
mHideInput = hideInput;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Gets whether the command hides the standard output log
|
||||
*/
|
||||
public boolean getHideStandardOutput() {
|
||||
return mHideStandardOutput;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param hideStandardOutput Set this to hide the standard output to the logger
|
||||
*/
|
||||
public void setHideStandardOutput(boolean hideStandardOutput) {
|
||||
mHideStandardOutput = hideStandardOutput;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Gets whether the command hides the error output log
|
||||
*/
|
||||
public boolean getHideErrorOutput() {
|
||||
return mHideErrorOutput;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param hideErrorOutput Set this to hide the error output to the logger
|
||||
*/
|
||||
public void setHideErrorOutput(boolean hideErrorOutput) {
|
||||
mHideErrorOutput = hideErrorOutput;
|
||||
}
|
||||
|
||||
/**
|
||||
* If this value is set the command will read the standard output as binary
|
||||
*/
|
||||
private boolean mBinaryStandardOutput = false;
|
||||
|
||||
/**
|
||||
* @return Gets whether the output will be binary
|
||||
*/
|
||||
public boolean getBinaryStandardOutput() {
|
||||
return mBinaryStandardOutput;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param binaryStandardOutput Set this if you want a binary output
|
||||
*/
|
||||
public void setBinaryStandardOutput(boolean binaryStandardOutput) {
|
||||
mBinaryStandardOutput = binaryStandardOutput;
|
||||
}
|
||||
|
||||
/**
|
||||
* The timeout for this command in milliseconds
|
||||
*/
|
||||
private long mTimeout;
|
||||
|
||||
/**
|
||||
* @return Gets the timeout for this command in milliseconds
|
||||
*/
|
||||
public long getTimeout() {
|
||||
return mTimeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the timeout for this command in milliseconds
|
||||
* @param timeout Timeout
|
||||
* @return Itself
|
||||
*/
|
||||
public SuperUserCommand setTimeout(long timeout) {
|
||||
mTimeout = timeout;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Gets the executed commands
|
||||
*/
|
||||
public String[] getCommands() {
|
||||
return mCommands;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Gets the standard output
|
||||
*/
|
||||
public String[] getStandardOutput() {
|
||||
return mOutputStandard;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Gets the error output
|
||||
*/
|
||||
public String[] getErrorOutput() {
|
||||
return mOutputError;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Gets the standard output as binary
|
||||
*/
|
||||
public byte[] getStandardOutputBinary() {
|
||||
return mOutputStandardBinary;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Gets whether the command was executed without errors, even without error outputs from the command.
|
||||
*/
|
||||
public boolean commandWasSuccessful() {
|
||||
return (!mSuperUserFailed && mOutputError.length == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Gets whether the command was granted superuser permissions, but maybe has some error outputs.
|
||||
*/
|
||||
public boolean superuserWasSuccessful() {
|
||||
return (!mSuperUserFailed);
|
||||
}
|
||||
|
||||
/**
|
||||
* The async execution thread
|
||||
*/
|
||||
private SuperUserCommandThread mThread;
|
||||
|
||||
/**
|
||||
* The async callback
|
||||
*/
|
||||
private SuperUserCommandCallback mCallback;
|
||||
|
||||
/**
|
||||
* Creates a command with one command line
|
||||
* @param command The command
|
||||
*/
|
||||
public SuperUserCommand(String command) {
|
||||
this(new String[] {command});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a command with multiple command lines
|
||||
* @param commands The command lines
|
||||
*/
|
||||
public SuperUserCommand(String[] commands) {
|
||||
mCommands = commands;
|
||||
|
||||
// Default timeout
|
||||
mTimeout = DEFAULT_COMMAND_TIMEOUT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the command asynchronously.
|
||||
* Please notice that the commands will only executed one after another.
|
||||
* The command will wait until the su process is free.
|
||||
* @param callback The callback instance
|
||||
*/
|
||||
public void executeAsync(SuperUserCommandCallback callback) {
|
||||
mCallback = callback;
|
||||
|
||||
// Thread is running
|
||||
if (mThread != null) return;
|
||||
|
||||
// Create a new thread
|
||||
mThread = new SuperUserCommandThread();
|
||||
|
||||
// Starts a thread
|
||||
mThread.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the command and return whether the command was executed.
|
||||
* It will only return false if the app wasn't granted superuser permissions, like {@link #superuserWasSuccessful()}.
|
||||
* It will also return true if the command itself returns error outputs. To check this case you should use {@link #commandWasSuccessful()} instead.
|
||||
* Please consider to use {@link #executeAsync} instead of this and execute the command asynchronously.
|
||||
* @return Gets whether the execution was successful.
|
||||
*/
|
||||
public boolean execute() {
|
||||
String tmpLine;
|
||||
List<String> tmpList = new ArrayList<>();
|
||||
|
||||
mSuperUserFailed = false;
|
||||
|
||||
// Opps, we don't have superuser permissions
|
||||
// Did you run SuperUser.askForPermissions()?
|
||||
if (!SuperUser.hasPermissions()) {
|
||||
mSuperUserFailed = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Thread safe
|
||||
synchronized (SuperUser.getProcess()) {
|
||||
try {
|
||||
// Gets the streams
|
||||
DataOutputStream dataOutputStream = new DataOutputStream(SuperUser.getProcess().getOutputStream());
|
||||
BufferedReader bufferedInputReader = new BufferedReader(new InputStreamReader(SuperUser.getProcess().getInputStream()));
|
||||
BufferedReader bufferedErrorReader = new BufferedReader(new InputStreamReader(SuperUser.getProcess().getErrorStream()));
|
||||
|
||||
// Sends the command
|
||||
for (String command : mCommands) {
|
||||
dataOutputStream.writeBytes(command + "\n");
|
||||
}
|
||||
dataOutputStream.flush();
|
||||
|
||||
// TODO: This class cannot execute commands without any output (standard and error). These commands will run until the timeout will kill them!
|
||||
|
||||
// Start waiting
|
||||
long timeStarted = System.currentTimeMillis();
|
||||
|
||||
// Wait for first data
|
||||
while (!bufferedInputReader.ready() && !bufferedErrorReader.ready()) {
|
||||
try {
|
||||
// Waiting
|
||||
Thread.sleep(10);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
long timeNow = System.currentTimeMillis();
|
||||
|
||||
// TimeOut
|
||||
if (timeNow - timeStarted >= mTimeout) break;
|
||||
}
|
||||
|
||||
// We want to read the data as binary
|
||||
if (mBinaryStandardOutput) {
|
||||
int len;
|
||||
byte[] buffer = new byte[1024];
|
||||
|
||||
// Byte buffer
|
||||
ByteBuffer byteBuffer = new ByteBuffer();
|
||||
|
||||
// Need the direct input stream
|
||||
InputStream inputStream = SuperUser.getProcess().getInputStream();
|
||||
|
||||
do {
|
||||
while (bufferedInputReader.ready()) {
|
||||
// Read to buffer
|
||||
len = inputStream.read(buffer);
|
||||
|
||||
// Write to buffer
|
||||
byteBuffer.append(buffer, 0, len);
|
||||
}
|
||||
|
||||
// Fix: Wait for the buffer and try again
|
||||
try {
|
||||
// Sometimes cat is to slow.
|
||||
// If there is no data anymore we will wait 100ms and check again.
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} while (bufferedInputReader.ready());
|
||||
|
||||
mOutputStandardBinary = byteBuffer.toByteArray();
|
||||
} else {
|
||||
// Reads the standard output as text
|
||||
tmpList.clear();
|
||||
while (bufferedInputReader.ready()) {
|
||||
tmpLine = bufferedInputReader.readLine();
|
||||
|
||||
// End of data
|
||||
if (tmpLine == null) break;
|
||||
|
||||
tmpList.add(tmpLine);
|
||||
}
|
||||
// Convert list to array
|
||||
mOutputStandard = tmpList.toArray(new String[tmpList.size()]);
|
||||
}
|
||||
|
||||
// Reads the error output
|
||||
tmpList.clear();
|
||||
while (bufferedErrorReader.ready()) {
|
||||
tmpLine = bufferedErrorReader.readLine();
|
||||
|
||||
// End of data
|
||||
if (tmpLine == null) break;
|
||||
|
||||
tmpList.add(tmpLine);
|
||||
}
|
||||
// Convert list to array
|
||||
mOutputError = tmpList.toArray(new String[tmpList.size()]);
|
||||
|
||||
// Done
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
|
||||
mSuperUserFailed = true;
|
||||
|
||||
// Command failed
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Thread to executes the command asynchronously
|
||||
*/
|
||||
private class SuperUserCommandThread extends Thread {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
super.run();
|
||||
|
||||
// Executes the command
|
||||
execute();
|
||||
|
||||
if (mCallback != null)
|
||||
mCallback.onFinished(SuperUserCommand.this);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2015 David Schulte
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package rc.jcg.superuser;
|
||||
|
||||
/**
|
||||
* Callback class if the async execution is finish
|
||||
*/
|
||||
public interface SuperUserCommandCallback {
|
||||
/**
|
||||
* Callback event
|
||||
* @param command The command that finished
|
||||
*/
|
||||
void onFinished(SuperUserCommand command);
|
||||
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
package rc.jcg.superuser;
|
||||
|
||||
public interface SuperUserPermissionRequestListener {
|
||||
void superUserGranted(boolean granted);
|
||||
}
|
|
@ -1,115 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2015 David Schulte
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package rc.jcg.superuser;
|
||||
|
||||
/**
|
||||
* Tools for the superuser
|
||||
*/
|
||||
public class SuperUserTools {
|
||||
/**
|
||||
* Private constructor
|
||||
*/
|
||||
private SuperUserTools() {}
|
||||
|
||||
/**
|
||||
* Copy a file with root permissions
|
||||
* @param src Source file
|
||||
* @param dest Destination file
|
||||
* @return Returns whether the command was successful
|
||||
*/
|
||||
public static boolean fileCopy(String src, String dest) {
|
||||
SuperUserCommand superUserCommand = new SuperUserCommand(new String[] {
|
||||
"rm -f '" + dest + "'", // Remove destination file
|
||||
"cat '" + src + "' >> '" + dest + "'", // Using cat to copy file instead of cp, because you can use it without busybox
|
||||
"chmod 0777 '" + dest + "'", // Change the access mode to all users (chown sdcard_r will fail on some devices)
|
||||
"echo 'done'" // Fix to prevent the 'no output' bug in SuperUserCommand
|
||||
});
|
||||
|
||||
// Don't spam the log
|
||||
superUserCommand.setHideStandardOutput(true);
|
||||
|
||||
// Executes the command
|
||||
superUserCommand.execute();
|
||||
|
||||
// Superuser permissions and command are successful
|
||||
return superUserCommand.commandWasSuccessful();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the file exists
|
||||
* @param path The path to check
|
||||
* @return Returns whether the path exists
|
||||
*/
|
||||
public static boolean fileExists(String path) {
|
||||
SuperUserCommand superUserCommand = new SuperUserCommand("ls '" + path + "'");
|
||||
|
||||
// Don't spam the log
|
||||
superUserCommand.setHideStandardOutput(true);
|
||||
|
||||
// Executes the command
|
||||
superUserCommand.execute();
|
||||
|
||||
// Superuser permissions and command are successful
|
||||
return superUserCommand.commandWasSuccessful();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets all bytes from one file
|
||||
* @param path The path to the file
|
||||
* @return Returns the byte array or null if the file doesn't exists
|
||||
*/
|
||||
public static byte[] fileReadToByteArray(String path) {
|
||||
SuperUserCommand superUserCommand = new SuperUserCommand("cat '" + path + "'");
|
||||
|
||||
// Don't spam the log with binary code
|
||||
superUserCommand.setHideInput(true);
|
||||
superUserCommand.setHideStandardOutput(true);
|
||||
superUserCommand.setBinaryStandardOutput(true);
|
||||
|
||||
// Executes the command
|
||||
superUserCommand.execute();
|
||||
|
||||
// Failed
|
||||
if (!superUserCommand.commandWasSuccessful())
|
||||
return null;
|
||||
|
||||
return superUserCommand.getStandardOutputBinary();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all bytes from one file
|
||||
* @param path The path to the file
|
||||
* @param callback The callback
|
||||
*/
|
||||
public static void fileReadToByteArrayAsync(String path, SuperUserCommandCallback callback) {
|
||||
SuperUserCommand superUserCommand = new SuperUserCommand("cat '" + path + "'");
|
||||
|
||||
// Don't spam the log with binary code
|
||||
superUserCommand.setHideInput(true);
|
||||
superUserCommand.setHideStandardOutput(true);
|
||||
superUserCommand.setBinaryStandardOutput(true);
|
||||
|
||||
superUserCommand.executeAsync(callback);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue