Refactor: split into modules autojs, common, app and automator
This commit is contained in:
1
common/.gitignore
vendored
Normal file
1
common/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/build
|
||||
32
common/build.gradle
Normal file
32
common/build.gradle
Normal file
@@ -0,0 +1,32 @@
|
||||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
compileSdkVersion 25
|
||||
buildToolsVersion "25.0.2"
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 19
|
||||
targetSdkVersion 25
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
|
||||
exclude group: 'com.android.support', module: 'support-annotations'
|
||||
})
|
||||
compile 'com.android.support:appcompat-v7:25.3.0'
|
||||
testCompile 'junit:junit:4.12'
|
||||
compile 'org.testng:testng:6.9.6'
|
||||
}
|
||||
25
common/proguard-rules.pro
vendored
Normal file
25
common/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in E:\YiBin\eclipse\Android_SDK_windows/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 *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.stardust;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Instrumentation test, which will execute on an Android device.
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ExampleInstrumentedTest {
|
||||
@Test
|
||||
public void useAppContext() throws Exception {
|
||||
// Context of the app under test.
|
||||
Context appContext = InstrumentationRegistry.getTargetContext();
|
||||
|
||||
assertEquals("com.stardust.test", appContext.getPackageName());
|
||||
}
|
||||
}
|
||||
13
common/src/main/AndroidManifest.xml
Normal file
13
common/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,13 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
|
||||
package="com.stardust"
|
||||
>
|
||||
|
||||
<application android:allowBackup="true"
|
||||
android:label="@string/app_name"
|
||||
android:supportsRtl="true"
|
||||
>
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
239
common/src/main/java/com/stardust/pio/PFile.java
Normal file
239
common/src/main/java/com/stardust/pio/PFile.java
Normal file
@@ -0,0 +1,239 @@
|
||||
package com.stardust.pio;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/4/1.
|
||||
*/
|
||||
|
||||
public class PFile {
|
||||
|
||||
private static final int BUFFER_SIZE = 8192;
|
||||
|
||||
public static PFile open(String path, String mode) {
|
||||
switch (mode) {
|
||||
case "r":
|
||||
return new PReadableFile(path);
|
||||
case "w":
|
||||
return new PWritableFile();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean createIfNotExists(String path) {
|
||||
ensureDirectory(path);
|
||||
File file = new File(path);
|
||||
if (!file.exists()) {
|
||||
try {
|
||||
return file.createNewFile();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean ensureDirectory(String path) {
|
||||
int i = path.lastIndexOf("\\");
|
||||
if (i < 0)
|
||||
i = path.lastIndexOf("/");
|
||||
if (i >= 0) {
|
||||
String folder = path.substring(0, i);
|
||||
File file = new File(folder);
|
||||
if (file.exists())
|
||||
return true;
|
||||
return file.mkdirs();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static String read(String path, String encoding) {
|
||||
return read(new File(path), encoding);
|
||||
}
|
||||
|
||||
public static String read(String path) {
|
||||
return read(new File(path));
|
||||
}
|
||||
|
||||
|
||||
public static String read(File file, String encoding) {
|
||||
try {
|
||||
return read(new FileInputStream(file), encoding);
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static String read(File file) {
|
||||
return read(file, "utf-8");
|
||||
}
|
||||
|
||||
public static String read(InputStream is, String encoding) {
|
||||
try {
|
||||
byte[] bytes = new byte[is.available()];
|
||||
is.read(bytes);
|
||||
return new String(bytes, encoding);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static String read(InputStream inputStream) {
|
||||
return read(inputStream, "utf-8");
|
||||
}
|
||||
|
||||
public static boolean copyRaw(Context context, int rawId, String path) {
|
||||
InputStream is = context.getResources().openRawResource(rawId);
|
||||
return copyStream(is, path);
|
||||
}
|
||||
|
||||
public static boolean copyStream(InputStream is, String path) {
|
||||
if (!ensureDirectory(path))
|
||||
return false;
|
||||
File file = new File(path);
|
||||
try {
|
||||
if (!file.exists())
|
||||
if (!file.createNewFile())
|
||||
return false;
|
||||
FileOutputStream fos = new FileOutputStream(file);
|
||||
return write(is, fos);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean write(InputStream is, OutputStream os) {
|
||||
byte[] buffer = new byte[BUFFER_SIZE];
|
||||
try {
|
||||
while (is.available() > 0) {
|
||||
int n = is.read(buffer);
|
||||
os.write(buffer, 0, n);
|
||||
}
|
||||
is.close();
|
||||
os.close();
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static boolean copy(String pathFrom, String pathTo) {
|
||||
try {
|
||||
return copyStream(new FileInputStream(pathFrom), pathTo);
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean copyAsset(Context context, String assetFile, String path) {
|
||||
try {
|
||||
return copyStream(context.getAssets().open(assetFile), path);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static String renameWithoutExtension(String path, String newName) {
|
||||
File file = new File(path);
|
||||
File newFile = new File(file.getParent(), newName + "." + getExtension(file.getName()));
|
||||
file.renameTo(newFile);
|
||||
return newFile.getAbsolutePath();
|
||||
}
|
||||
|
||||
public static String getExtension(String fileName) {
|
||||
int i = fileName.lastIndexOf('.');
|
||||
if (i < 0)
|
||||
return "";
|
||||
return fileName.substring(i + 1);
|
||||
}
|
||||
|
||||
public static boolean write(String path, String text) {
|
||||
return write(new File(path), text);
|
||||
}
|
||||
|
||||
public static boolean write(File file, String text) {
|
||||
try {
|
||||
return write(new FileOutputStream(file), text);
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean write(OutputStream outputStream, String text) {
|
||||
try {
|
||||
outputStream.write(text.getBytes());
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static String generateNotExistingPath(String path, String extension) {
|
||||
if (!new File(path + extension).exists())
|
||||
return path + extension;
|
||||
int i = 0;
|
||||
while (true) {
|
||||
String pathI = path + "(" + i + ")" + extension;
|
||||
if (!new File(pathI).exists())
|
||||
return pathI;
|
||||
i++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static String getNameWithoutExtension(String fileName) {
|
||||
int a = fileName.lastIndexOf('/');
|
||||
if (a < 0)
|
||||
a = fileName.lastIndexOf('\\');
|
||||
int b = fileName.lastIndexOf('.');
|
||||
if (a < 0)
|
||||
a = -1;
|
||||
if (b < 0)
|
||||
b = fileName.length();
|
||||
fileName = fileName.substring(a + 1, b);
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public static File copyAssetToTmpFile(Context context, String path) {
|
||||
String extension = getExtension(path);
|
||||
String name = getNameWithoutExtension(path);
|
||||
if (name.length() < 5) {
|
||||
name += name.hashCode();
|
||||
}
|
||||
try {
|
||||
File tmpFile = File.createTempFile(name, "." + extension, context.getCacheDir());
|
||||
copyAsset(context, path, tmpFile.getPath());
|
||||
return tmpFile;
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean deleteRecursively(File file) {
|
||||
if (file.isFile())
|
||||
return file.delete();
|
||||
for (File child : file.listFiles()) {
|
||||
if (!deleteRecursively(child))
|
||||
return false;
|
||||
}
|
||||
return file.delete();
|
||||
}
|
||||
}
|
||||
106
common/src/main/java/com/stardust/pio/PReadableFile.java
Normal file
106
common/src/main/java/com/stardust/pio/PReadableFile.java
Normal file
@@ -0,0 +1,106 @@
|
||||
package com.stardust.pio;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/4/1.
|
||||
*/
|
||||
|
||||
public class PReadableFile extends PFile {
|
||||
|
||||
private BufferedReader mBufferedReader;
|
||||
private FileInputStream mFileInputStream;
|
||||
private int mBufferingSize;
|
||||
private String mEncoding;
|
||||
|
||||
public PReadableFile(String path) {
|
||||
this(path, Charset.defaultCharset().name());
|
||||
}
|
||||
|
||||
public PReadableFile(String path, String encoding) {
|
||||
this(path, encoding, -1);
|
||||
}
|
||||
|
||||
public PReadableFile(String path, String encoding, int bufferingSize) {
|
||||
mEncoding = encoding;
|
||||
mBufferingSize = bufferingSize;
|
||||
try {
|
||||
mFileInputStream = new FileInputStream(path);
|
||||
} catch (FileNotFoundException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void ensureBufferReader() {
|
||||
if (mBufferedReader == null) {
|
||||
try {
|
||||
if (mBufferingSize == -1)
|
||||
mBufferedReader = new BufferedReader(new InputStreamReader(mFileInputStream, mEncoding));
|
||||
else
|
||||
mBufferedReader = new BufferedReader(new InputStreamReader(mFileInputStream, mEncoding), mBufferingSize);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public String read() {
|
||||
try {
|
||||
byte[] data = new byte[mFileInputStream.available()];
|
||||
mFileInputStream.read(data);
|
||||
return new String(data, mEncoding);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public String read(int size) {
|
||||
ensureBufferReader();
|
||||
try {
|
||||
char[] chars = new char[size];
|
||||
int len = mBufferedReader.read(chars);
|
||||
return new String(chars, 0, len);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public String readline() {
|
||||
ensureBufferReader();
|
||||
try {
|
||||
return mBufferedReader.readLine();
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public String[] readlines() {
|
||||
ensureBufferReader();
|
||||
List<String> lines = new ArrayList<>();
|
||||
try {
|
||||
while (mBufferedReader.ready()) {
|
||||
lines.add(mBufferedReader.readLine());
|
||||
}
|
||||
return lines.toArray(new String[lines.size()]);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void close() {
|
||||
try {
|
||||
if (mBufferedReader != null) {
|
||||
mBufferedReader.close();
|
||||
} else {
|
||||
mFileInputStream.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
15
common/src/main/java/com/stardust/pio/PWritableFile.java
Normal file
15
common/src/main/java/com/stardust/pio/PWritableFile.java
Normal file
@@ -0,0 +1,15 @@
|
||||
package com.stardust.pio;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/4/1.
|
||||
*/
|
||||
|
||||
public class PWritableFile extends PFile {
|
||||
|
||||
public PWritableFile(){
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.stardust.pio;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/4/1.
|
||||
*/
|
||||
|
||||
public class UncheckedIOException extends RuntimeException {
|
||||
|
||||
public UncheckedIOException(IOException cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
27
common/src/main/java/com/stardust/util/AssetsCache.java
Normal file
27
common/src/main/java/com/stardust/util/AssetsCache.java
Normal file
@@ -0,0 +1,27 @@
|
||||
package com.stardust.util;
|
||||
|
||||
import android.content.res.AssetManager;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/3/14.
|
||||
*/
|
||||
|
||||
public class AssetsCache {
|
||||
|
||||
private Map<String, String> mCache = new HashMap<>();
|
||||
|
||||
|
||||
public String read(AssetManager manager, String path) throws IOException {
|
||||
String str = mCache.get(path);
|
||||
if (str == null) {
|
||||
str = FileUtils.readString(manager.open(path));
|
||||
mCache.put(path, str);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package com.stardust.util;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.support.v4.widget.DrawerLayout;
|
||||
import android.widget.Toast;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/2/3.
|
||||
*/
|
||||
public interface BackPressedHandler {
|
||||
|
||||
boolean onBackPressed(Activity activity);
|
||||
|
||||
class Observer implements BackPressedHandler {
|
||||
|
||||
private List<BackPressedHandler> mBackPressedHandlers = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public boolean onBackPressed(Activity activity) {
|
||||
for (BackPressedHandler handler : mBackPressedHandlers) {
|
||||
if (handler.onBackPressed(activity)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void registerHandler(BackPressedHandler handler) {
|
||||
mBackPressedHandlers.add(handler);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class DoublePressExit implements BackPressedHandler {
|
||||
|
||||
private final Activity mActivity;
|
||||
private long mLastPressedMillis;
|
||||
private long mDoublePressInterval = 1000;
|
||||
private String mNotice;
|
||||
|
||||
public DoublePressExit(Activity activity, int noticeResId) {
|
||||
this(activity, activity.getString(noticeResId));
|
||||
}
|
||||
|
||||
public DoublePressExit(Activity activity, String notice) {
|
||||
mActivity = activity;
|
||||
mNotice = notice;
|
||||
}
|
||||
|
||||
public DoublePressExit doublePressInterval(long doublePressInterval) {
|
||||
mDoublePressInterval = doublePressInterval;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onBackPressed(Activity activity) {
|
||||
if (System.currentTimeMillis() - mLastPressedMillis < mDoublePressInterval) {
|
||||
mActivity.finish();
|
||||
} else {
|
||||
mLastPressedMillis = System.currentTimeMillis();
|
||||
Toast.makeText(mActivity, mNotice, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class DrawerAutoClose implements BackPressedHandler {
|
||||
|
||||
private DrawerLayout mDrawerLayout;
|
||||
private int mGravity;
|
||||
|
||||
public DrawerAutoClose(DrawerLayout drawerLayout, int gravity){
|
||||
mDrawerLayout = drawerLayout;
|
||||
mGravity = gravity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onBackPressed(Activity activity) {
|
||||
if (mDrawerLayout.isDrawerOpen(mGravity)) {
|
||||
mDrawerLayout.closeDrawer(mGravity);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
18
common/src/main/java/com/stardust/util/ClipboardUtil.java
Normal file
18
common/src/main/java/com/stardust/util/ClipboardUtil.java
Normal file
@@ -0,0 +1,18 @@
|
||||
package com.stardust.util;
|
||||
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/3/10.
|
||||
*/
|
||||
|
||||
public class ClipboardUtil {
|
||||
|
||||
|
||||
public static void setClip(Context context, CharSequence text) {
|
||||
((ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE)).setPrimaryClip(ClipData.newPlainText("", text));
|
||||
}
|
||||
}
|
||||
11
common/src/main/java/com/stardust/util/Consumer.java
Normal file
11
common/src/main/java/com/stardust/util/Consumer.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package com.stardust.util;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/3/10.
|
||||
*/
|
||||
|
||||
public interface Consumer<T> {
|
||||
|
||||
void accept(T t);
|
||||
|
||||
}
|
||||
79
common/src/main/java/com/stardust/util/FileSorter.java
Normal file
79
common/src/main/java/com/stardust/util/FileSorter.java
Normal file
@@ -0,0 +1,79 @@
|
||||
package com.stardust.util;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/3/31.
|
||||
*/
|
||||
|
||||
public class FileSorter {
|
||||
|
||||
public static void sort(File[] files) {
|
||||
Arrays.sort(files, new Comparator<File>() {
|
||||
@Override
|
||||
public int compare(File o1, File o2) {
|
||||
if (o1.isDirectory() != o2.isDirectory())
|
||||
return o1.isDirectory() ? Integer.MIN_VALUE : Integer.MAX_VALUE;
|
||||
return o1.getName().compareTo(o2.getName());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static class TestSuite {
|
||||
|
||||
@Test
|
||||
public void testEngFileSort() {
|
||||
File file1 = new File("d:/a.txt");
|
||||
File file2 = new File("e:/b.txt");
|
||||
File file3 = new File("c:/c.txt");
|
||||
File[] files = {file2, file3, file1};
|
||||
sort(files);
|
||||
Assert.assertArrayEquals(new File[]{file1, file2, file3}, files);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEngFileSortWithDirectory() {
|
||||
File dir1 = new File("d:/");
|
||||
File dir2 = new File("e:/");
|
||||
File file1 = new File("e:/a.txt");
|
||||
File file2 = new File("e:/b.txt");
|
||||
File file3 = new File("d:/c.txt");
|
||||
Assert.assertTrue(dir1.isDirectory());
|
||||
Assert.assertTrue(dir2.isDirectory());
|
||||
File[] files = {file2, file3, dir1, file1, dir2};
|
||||
sort(files);
|
||||
Assert.assertArrayEquals(new File[]{dir1, dir2, file1, file2, file3}, files);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCnFileSort() {
|
||||
File file1 = new File("a.txt");
|
||||
File file2 = new File("b.txt");
|
||||
File file3 = new File("啊.txt");
|
||||
File file4 = new File("啊啊.txt");
|
||||
File[] files = {file2, file4, file3, file1};
|
||||
sort(files);
|
||||
Assert.assertArrayEquals(new File[]{file1, file2, file3, file4}, files);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCnFileSortWithDirectory() {
|
||||
File dir1 = new File("d:/整理/");
|
||||
File dir2 = new File("d:/迅雷下载/");
|
||||
File file1 = new File("d:/整理/a.txt");
|
||||
File file2 = new File("啊.txt");
|
||||
File file3 = new File("啊啊.txt");
|
||||
Assert.assertTrue(dir1.isDirectory());
|
||||
Assert.assertTrue(dir2.isDirectory());
|
||||
File[] files = {file2, file3, dir1, file1, dir2};
|
||||
sort(files);
|
||||
Assert.assertArrayEquals(new File[]{dir1, dir2, file1, file2, file3}, files);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
261
common/src/main/java/com/stardust/util/FileUtils.java
Normal file
261
common/src/main/java/com/stardust/util/FileUtils.java
Normal file
@@ -0,0 +1,261 @@
|
||||
package com.stardust.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/23.
|
||||
*/
|
||||
|
||||
public class FileUtils {
|
||||
|
||||
private static final int BUFFER_SIZE = 1024 * 100;
|
||||
|
||||
public static String getPath(Context context, Uri uri) throws URISyntaxException {
|
||||
if ("content".equalsIgnoreCase(uri.getScheme())) {
|
||||
String[] projection = {"_data"};
|
||||
Cursor cursor = null;
|
||||
|
||||
try {
|
||||
cursor = context.getContentResolver().query(uri, projection, null, null, null);
|
||||
int column_index = cursor.getColumnIndexOrThrow("_data");
|
||||
if (cursor.moveToFirst()) {
|
||||
return cursor.getString(column_index);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Eat it
|
||||
}
|
||||
} else if ("file".equalsIgnoreCase(uri.getScheme())) {
|
||||
return uri.getPath();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String getPath(InputStream inputStream) {
|
||||
if (inputStream instanceof FileInputStream) {
|
||||
FileInputStream fis = (FileInputStream) inputStream;
|
||||
try {
|
||||
Field field = fis.getClass().getDeclaredField("path");
|
||||
field.setAccessible(true);
|
||||
return (String) field.get(fis);
|
||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean createFileIfNotExists(String path) {
|
||||
ensureFolder(path);
|
||||
File file = new File(path);
|
||||
if (!file.exists()) {
|
||||
try {
|
||||
return file.createNewFile();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean ensureFolder(String path) {
|
||||
int i = path.lastIndexOf("\\");
|
||||
if (i < 0)
|
||||
i = path.lastIndexOf("/");
|
||||
if (i >= 0) {
|
||||
String folder = path.substring(0, i);
|
||||
File file = new File(folder);
|
||||
if (file.exists())
|
||||
return true;
|
||||
return file.mkdirs();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static String readString(File file, String encoding) {
|
||||
try {
|
||||
return readString(new FileInputStream(file), encoding);
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static String readString(File file) {
|
||||
return readString(file, "utf-8");
|
||||
}
|
||||
|
||||
public static String readString(InputStream is, String encoding) {
|
||||
try {
|
||||
byte[] bytes = new byte[is.available()];
|
||||
is.read(bytes);
|
||||
return new String(bytes, encoding);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static String readString(InputStream inputStream) {
|
||||
return readString(inputStream, "utf-8");
|
||||
}
|
||||
|
||||
public static boolean copy(Context context, int rawId, String path) {
|
||||
InputStream is = context.getResources().openRawResource(rawId);
|
||||
return copy(is, path);
|
||||
}
|
||||
|
||||
public static boolean copy(InputStream is, String path) {
|
||||
if (!ensureFolder(path))
|
||||
return false;
|
||||
File file = new File(path);
|
||||
try {
|
||||
if (!file.exists())
|
||||
if (!file.createNewFile())
|
||||
return false;
|
||||
FileOutputStream fos = new FileOutputStream(file);
|
||||
return copy(is, fos);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean copy(InputStream is, OutputStream os) {
|
||||
byte[] buffer = new byte[BUFFER_SIZE];
|
||||
try {
|
||||
while (is.available() > 0) {
|
||||
int n = is.read(buffer);
|
||||
os.write(buffer, 0, n);
|
||||
}
|
||||
is.close();
|
||||
os.close();
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static boolean copy(String pathFrom, String pathTo) {
|
||||
try {
|
||||
return copy(new FileInputStream(pathFrom), pathTo);
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean copyAsset(Context context, String assetFile, String path) {
|
||||
try {
|
||||
return copy(context.getAssets().open(assetFile), path);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static String renameWithoutExtension(String path, String newName) {
|
||||
File file = new File(path);
|
||||
File newFile = new File(file.getParent(), newName + "." + getExtension(file.getName()));
|
||||
file.renameTo(newFile);
|
||||
return newFile.getAbsolutePath();
|
||||
}
|
||||
|
||||
public static String getExtension(String fileName) {
|
||||
int i = fileName.lastIndexOf('.');
|
||||
if (i < 0)
|
||||
return "";
|
||||
return fileName.substring(i + 1);
|
||||
}
|
||||
|
||||
|
||||
public static boolean writeString(String path, String text) {
|
||||
return writeString(new File(path), text);
|
||||
}
|
||||
|
||||
public static boolean writeString(File file, String text) {
|
||||
try {
|
||||
return writeString(new FileOutputStream(file), text);
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean writeString(OutputStream outputStream, String text) {
|
||||
try {
|
||||
outputStream.write(text.getBytes());
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static String generateNotExistingPath(String path, String extension) {
|
||||
if (!new File(path + extension).exists())
|
||||
return path + extension;
|
||||
int i = 0;
|
||||
while (true) {
|
||||
String pathI = path + "(" + i + ")" + extension;
|
||||
if (!new File(pathI).exists())
|
||||
return pathI;
|
||||
i++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static String getNameWithoutExtension(String fileName) {
|
||||
int a = fileName.lastIndexOf('/');
|
||||
if (a < 0)
|
||||
a = fileName.lastIndexOf('\\');
|
||||
int b = fileName.lastIndexOf('.');
|
||||
if (a < 0)
|
||||
a = -1;
|
||||
if (b < 0)
|
||||
b = fileName.length();
|
||||
fileName = fileName.substring(a + 1, b);
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public static File copyAssetToTmpFile(Context context, String path) {
|
||||
String extension = getExtension(path);
|
||||
String name = getNameWithoutExtension(path);
|
||||
if (name.length() < 5) {
|
||||
name += name.hashCode();
|
||||
}
|
||||
try {
|
||||
File tmpFile = File.createTempFile(name, "." + extension, context.getCacheDir());
|
||||
copyAsset(context, path, tmpFile.getPath());
|
||||
return tmpFile;
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean deleteAll(File file) {
|
||||
if (file.isFile())
|
||||
return file.delete();
|
||||
for (File child : file.listFiles()) {
|
||||
if (!deleteAll(child))
|
||||
return false;
|
||||
}
|
||||
return file.delete();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.stardust.util;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.widget.Toast;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/3/10.
|
||||
*/
|
||||
|
||||
public class FloatingWindowUtils {
|
||||
|
||||
public static boolean checkFloatingWindowPermission(Context context, int messageResId) {
|
||||
if (!isFloatingWindowPermitted(context)) {
|
||||
Toast.makeText(context, messageResId, Toast.LENGTH_SHORT).show();
|
||||
IntentUtil.goToAppDetailSettings(context, context.getPackageName());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static boolean isFloatingWindowPermitted(Context context) {
|
||||
PackageManager pm = context.getPackageManager();
|
||||
return pm.checkPermission(Manifest.permission.SYSTEM_ALERT_WINDOW, context.getPackageName())
|
||||
== PackageManager.PERMISSION_GRANTED;
|
||||
}
|
||||
|
||||
}
|
||||
84
common/src/main/java/com/stardust/util/IntentUtil.java
Normal file
84
common/src/main/java/com/stardust/util/IntentUtil.java
Normal file
@@ -0,0 +1,84 @@
|
||||
package com.stardust.util;
|
||||
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
|
||||
public class IntentUtil {
|
||||
|
||||
public static boolean chatWithQQ(Context context, String qq) {
|
||||
try {
|
||||
String url = "mqqwpa://im/chat?chat_type=wpa&uin=" + qq;
|
||||
context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
|
||||
return true;
|
||||
} catch (Exception exception) {
|
||||
exception.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean joinQQGroup(Context context, String key) {
|
||||
Intent intent = new Intent().addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent.setData(Uri.parse("mqqopensdkapi://bizAgent/qm/qr?url=http%3A%2F%2Fqm.qq.com%2Fcgi-bin%2Fqm%2Fqr%3Ffrom%3Dapp%26p%3Dandroid%26k%3D" + key));
|
||||
try {
|
||||
context.startActivity(intent);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void sendMailTo(Context context, String sendTo, @Nullable String title, @Nullable String content) {
|
||||
Uri uri = Uri.parse("mailto:" + sendTo);
|
||||
String[] email = {sendTo};
|
||||
Intent intent = new Intent(Intent.ACTION_SENDTO, uri).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent.putExtra(Intent.EXTRA_CC, email);
|
||||
if (title != null)
|
||||
intent.putExtra(Intent.EXTRA_SUBJECT, title);
|
||||
if (content != null)
|
||||
intent.putExtra(Intent.EXTRA_TEXT, content);
|
||||
context.startActivity(Intent.createChooser(intent, ""));
|
||||
}
|
||||
|
||||
public static void sendMailTo(Context context, String sendTo) {
|
||||
sendMailTo(context, sendTo, null, null);
|
||||
}
|
||||
|
||||
public static boolean browse(Context context, String link) {
|
||||
try {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(link)).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
context.startActivity(intent);
|
||||
return true;
|
||||
} catch (ActivityNotFoundException ignored) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void shareText(Context context, String text) {
|
||||
context.startActivity(new Intent(Intent.ACTION_SEND)
|
||||
.putExtra(Intent.EXTRA_TEXT, text)
|
||||
.setType("text/plain"));
|
||||
}
|
||||
|
||||
public static boolean goToAppDetailSettings(Context context, String packageName) {
|
||||
try {
|
||||
Intent i = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
|
||||
i.addCategory(Intent.CATEGORY_DEFAULT);
|
||||
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
i.setData(Uri.parse("package:" + packageName));
|
||||
context.startActivity(i);
|
||||
return true;
|
||||
} catch (ActivityNotFoundException ignored) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean goToAppDetailSettings(Context context) {
|
||||
return goToAppDetailSettings(context, context.getPackageName());
|
||||
}
|
||||
}
|
||||
58
common/src/main/java/com/stardust/util/LimitedHashMap.java
Normal file
58
common/src/main/java/com/stardust/util/LimitedHashMap.java
Normal file
@@ -0,0 +1,58 @@
|
||||
package com.stardust.util;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/3/31.
|
||||
*/
|
||||
|
||||
public class LimitedHashMap<K, V> extends LinkedHashMap<K, V> {
|
||||
|
||||
private int mMaxSize;
|
||||
|
||||
public LimitedHashMap(int maxSize) {
|
||||
super(4, 0.75f, true);
|
||||
mMaxSize = maxSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean removeEldestEntry(Entry<K, V> eldest) {
|
||||
return size() > mMaxSize;
|
||||
}
|
||||
|
||||
|
||||
public static class TestSuite {
|
||||
|
||||
@org.testng.annotations.Test
|
||||
public void testAutoRemove() {
|
||||
LimitedHashMap<String, Integer> hashMap = new LimitedHashMap<>(5);
|
||||
hashMap.put("a", 1);
|
||||
hashMap.put("b", 2);
|
||||
hashMap.put("c", 3);
|
||||
hashMap.put("d", 4);
|
||||
hashMap.put("e", 5);
|
||||
hashMap.put("f", 6);
|
||||
assertFalse(hashMap.containsKey("a"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAutoReorder() {
|
||||
LimitedHashMap<String, Integer> hashMap = new LimitedHashMap<>(5);
|
||||
hashMap.put("a", 1);
|
||||
hashMap.put("b", 2);
|
||||
hashMap.put("c", 3);
|
||||
hashMap.put("d", 4);
|
||||
hashMap.put("e", 5);
|
||||
hashMap.get("a");
|
||||
hashMap.put("f", 6);
|
||||
assertTrue(hashMap.containsKey("a"));
|
||||
assertFalse(hashMap.containsKey("b"));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
37
common/src/main/java/com/stardust/util/MapEntries.java
Normal file
37
common/src/main/java/com/stardust/util/MapEntries.java
Normal file
@@ -0,0 +1,37 @@
|
||||
package com.stardust.util;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/26.
|
||||
*/
|
||||
|
||||
public class MapEntries<K, V> {
|
||||
|
||||
private Map<K, V> mMap;
|
||||
|
||||
public MapEntries() {
|
||||
this(new TreeMap<K, V>());
|
||||
}
|
||||
|
||||
public MapEntries(Map<K, V> map) {
|
||||
mMap = map;
|
||||
}
|
||||
|
||||
public MapEntries<K, V> entry(K key, V value) {
|
||||
mMap.put(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Map<K, V> map() {
|
||||
return mMap;
|
||||
}
|
||||
|
||||
public Map<K, V> putIn(Map<K, V> map) {
|
||||
map.putAll(mMap);
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
22
common/src/main/java/com/stardust/util/MessageEvent.java
Normal file
22
common/src/main/java/com/stardust/util/MessageEvent.java
Normal file
@@ -0,0 +1,22 @@
|
||||
package com.stardust.util;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/3/12.
|
||||
*/
|
||||
|
||||
public class MessageEvent {
|
||||
|
||||
public String message;
|
||||
public Object param;
|
||||
|
||||
public MessageEvent(String message, Object param) {
|
||||
this.message = message;
|
||||
this.param = param;
|
||||
}
|
||||
|
||||
|
||||
public MessageEvent(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
}
|
||||
260
common/src/main/java/com/stardust/util/Shell.java
Normal file
260
common/src/main/java/com/stardust/util/Shell.java
Normal file
@@ -0,0 +1,260 @@
|
||||
package com.stardust.util;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/20.
|
||||
* <p>
|
||||
* 来自网络~~
|
||||
*/
|
||||
|
||||
public class Shell {
|
||||
|
||||
|
||||
private static final String TAG = "Shell";
|
||||
|
||||
private final static String COMMAND_SU = "su";
|
||||
private final static String COMMAND_SH = "sh";
|
||||
private final static String COMMAND_EXIT = "exit\n";
|
||||
private final static String COMMAND_LINE_END = "\n";
|
||||
|
||||
private Process mProcess;
|
||||
private DataOutputStream mCommandOutputStream;
|
||||
private BufferedReader mSucceedReader;
|
||||
private BufferedReader mErrorReader;
|
||||
|
||||
private StringBuilder mSucceedOutput = new StringBuilder();
|
||||
private StringBuilder mErrorOutput = new StringBuilder();
|
||||
|
||||
public Shell() {
|
||||
this(false);
|
||||
}
|
||||
|
||||
public Shell(boolean root) {
|
||||
try {
|
||||
mProcess = new ProcessBuilder(root ? COMMAND_SU : COMMAND_SH).redirectErrorStream(true).start();
|
||||
mCommandOutputStream = new DataOutputStream(mProcess.getOutputStream());
|
||||
mSucceedReader = new BufferedReader(new InputStreamReader(mProcess.getInputStream()));
|
||||
mErrorReader = new BufferedReader(new InputStreamReader(mProcess.getErrorStream()));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public Shell execute(String command) {
|
||||
try {
|
||||
mCommandOutputStream.writeBytes(command);
|
||||
if (!command.endsWith(COMMAND_LINE_END)) {
|
||||
mCommandOutputStream.writeBytes(COMMAND_LINE_END);
|
||||
}
|
||||
mCommandOutputStream.flush();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Shell exitAndWaitFor() {
|
||||
exit();
|
||||
try {
|
||||
mProcess.waitFor();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Shell readAll() {
|
||||
return readSucceedOutput().readErrorOutput();
|
||||
}
|
||||
|
||||
public Shell readSucceedOutput() {
|
||||
try {
|
||||
while (mSucceedReader.ready()) {
|
||||
String line = mSucceedReader.readLine();
|
||||
mSucceedOutput.append(line).append("\n");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Shell readErrorOutput() {
|
||||
String line;
|
||||
try {
|
||||
while ((line = mErrorReader.readLine()) != null) {
|
||||
mErrorOutput.append(line).append("\n");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public StringBuilder getSucceedOutput() {
|
||||
return mSucceedOutput;
|
||||
}
|
||||
|
||||
public StringBuilder getErrorOutput() {
|
||||
return mErrorOutput;
|
||||
}
|
||||
|
||||
public Shell exit() {
|
||||
execute(COMMAND_EXIT);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Shell destroy() {
|
||||
mProcess.destroy();
|
||||
return this;
|
||||
}
|
||||
|
||||
public Process getProcess() {
|
||||
return mProcess;
|
||||
}
|
||||
|
||||
public BufferedReader getSucceedReader() {
|
||||
return mSucceedReader;
|
||||
}
|
||||
|
||||
public BufferedReader getErrorReader() {
|
||||
return mErrorReader;
|
||||
}
|
||||
|
||||
public int waitFor() {
|
||||
try {
|
||||
return mProcess.waitFor();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Command执行结果
|
||||
*
|
||||
* @author Mountain
|
||||
*/
|
||||
public static class CommandResult {
|
||||
public int code = -1;
|
||||
public String error;
|
||||
public String result;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ShellResult{" +
|
||||
"code=" + code +
|
||||
", error='" + error + '\'' +
|
||||
", result='" + result + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行命令—单条
|
||||
*
|
||||
* @param command
|
||||
* @param isRoot
|
||||
* @return
|
||||
*/
|
||||
public static CommandResult execCommand(String command, boolean isRoot) {
|
||||
String[] commands = command.split("\n");
|
||||
return execCommand(commands, isRoot);
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行命令-多条
|
||||
*
|
||||
* @param commands
|
||||
* @param isRoot
|
||||
* @return
|
||||
*/
|
||||
public static CommandResult execCommand(String[] commands, boolean isRoot) {
|
||||
CommandResult commandResult = new CommandResult();
|
||||
if (commands == null || commands.length == 0) return commandResult;
|
||||
Process process = null;
|
||||
DataOutputStream os = null;
|
||||
BufferedReader successResult = null;
|
||||
BufferedReader errorResult = null;
|
||||
StringBuilder successMsg = null;
|
||||
StringBuilder errorMsg = null;
|
||||
try {
|
||||
process = Runtime.getRuntime().exec(isRoot ? COMMAND_SU : COMMAND_SH);
|
||||
os = new DataOutputStream(process.getOutputStream());
|
||||
for (String command : commands) {
|
||||
if (command != null) {
|
||||
os.write(command.getBytes());
|
||||
os.writeBytes(COMMAND_LINE_END);
|
||||
os.flush();
|
||||
}
|
||||
}
|
||||
os.writeBytes(COMMAND_EXIT);
|
||||
os.flush();
|
||||
commandResult.code = process.waitFor();
|
||||
//获取错误信息
|
||||
successMsg = new StringBuilder();
|
||||
errorMsg = new StringBuilder();
|
||||
successResult = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||
errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream()));
|
||||
String s;
|
||||
while ((s = successResult.readLine()) != null) successMsg.append(s);
|
||||
while ((s = errorResult.readLine()) != null) errorMsg.append(s);
|
||||
commandResult.result = successMsg.toString();
|
||||
commandResult.error = errorMsg.toString();
|
||||
Log.i(TAG, commandResult.toString());
|
||||
} catch (Exception e) {
|
||||
String errmsg = e.getMessage();
|
||||
if (errmsg != null) {
|
||||
Log.e(TAG, errmsg);
|
||||
} else {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} finally {
|
||||
try {
|
||||
if (os != null) os.close();
|
||||
if (successResult != null) successResult.close();
|
||||
if (errorResult != null) errorResult.close();
|
||||
} catch (IOException e) {
|
||||
String errmsg = e.getMessage();
|
||||
if (errmsg != null) {
|
||||
Log.e(TAG, errmsg);
|
||||
} else {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (process != null) process.destroy();
|
||||
}
|
||||
return commandResult;
|
||||
}
|
||||
|
||||
public static Process exec(String[] commands, boolean isRoot) {
|
||||
try {
|
||||
Process process = Runtime.getRuntime().exec(isRoot ? COMMAND_SU : COMMAND_SH);
|
||||
DataOutputStream os = new DataOutputStream(process.getOutputStream());
|
||||
for (String command : commands) {
|
||||
if (command != null) {
|
||||
os.write(command.getBytes());
|
||||
os.writeBytes(COMMAND_LINE_END);
|
||||
os.flush();
|
||||
}
|
||||
}
|
||||
os.writeBytes(COMMAND_EXIT);
|
||||
os.flush();
|
||||
os.close();
|
||||
return process;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Process exec(String command, boolean isRoot) {
|
||||
return exec(command.split("\n"), isRoot);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.stardust.util;
|
||||
|
||||
import android.util.SparseArray;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/26.
|
||||
*/
|
||||
|
||||
public class SparseArrayEntries<E> {
|
||||
|
||||
private SparseArray<E> mSparseArray = new SparseArray<>();
|
||||
|
||||
public SparseArrayEntries<E> entry(int key, E value) {
|
||||
mSparseArray.put(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public SparseArray<E> sparseArray() {
|
||||
return mSparseArray;
|
||||
}
|
||||
|
||||
}
|
||||
107
common/src/main/java/com/stardust/util/StateObserver.java
Normal file
107
common/src/main/java/com/stardust/util/StateObserver.java
Normal file
@@ -0,0 +1,107 @@
|
||||
package com.stardust.util;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.support.v7.widget.SwitchCompat;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/2/3.
|
||||
*/
|
||||
|
||||
public class StateObserver {
|
||||
|
||||
public interface OnStateChangedListener {
|
||||
|
||||
void onStateChanged(boolean newState);
|
||||
|
||||
void initState(boolean state);
|
||||
}
|
||||
|
||||
|
||||
public static abstract class SimpleOnStateChangedListener<T> implements OnStateChangedListener {
|
||||
|
||||
@Override
|
||||
public void initState(boolean state) {
|
||||
onStateChanged(state);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private final Map<String, List<OnStateChangedListener>> mKeyStateListenersMap = new HashMap<>();
|
||||
private SharedPreferences mSharedPreferences;
|
||||
|
||||
public StateObserver(SharedPreferences sharedPreferences) {
|
||||
mSharedPreferences = sharedPreferences;
|
||||
}
|
||||
|
||||
public void register(final String key, SwitchCompat switchCompat) {
|
||||
final WeakReference<SwitchCompat> switchCompatWeakReference = new WeakReference<>(switchCompat);
|
||||
register(key, new SimpleOnStateChangedListener() {
|
||||
@Override
|
||||
public void onStateChanged(boolean newState) {
|
||||
if (switchCompatWeakReference.get() != null) {
|
||||
switchCompatWeakReference.get().setChecked(newState);
|
||||
} else {
|
||||
unregister(key, this);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void register(String key, OnStateChangedListener listener) {
|
||||
initState(key, listener);
|
||||
synchronized (mKeyStateListenersMap) {
|
||||
List<OnStateChangedListener> listeners = getListenerListOrCreateIfNotExists(key);
|
||||
listeners.add(listener);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void unregister(String key, OnStateChangedListener stateChangedListener) {
|
||||
synchronized (mKeyStateListenersMap) {
|
||||
List<OnStateChangedListener> listeners = mKeyStateListenersMap.get(key);
|
||||
if (listeners == null) {
|
||||
return;
|
||||
}
|
||||
listeners.remove(stateChangedListener);
|
||||
}
|
||||
}
|
||||
|
||||
public void setState(String key, boolean state) {
|
||||
synchronized (mKeyStateListenersMap) {
|
||||
List<OnStateChangedListener> listeners = mKeyStateListenersMap.get(key);
|
||||
if (listeners == null || listeners.isEmpty())
|
||||
return;
|
||||
mSharedPreferences.edit().putBoolean(key, state).apply();
|
||||
notifyBooleanStateChanged(listeners, state);
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyBooleanStateChanged(List<OnStateChangedListener> listeners, boolean state) {
|
||||
for (OnStateChangedListener listener : listeners) {
|
||||
listener.onStateChanged(state);
|
||||
}
|
||||
}
|
||||
|
||||
private void initState(String key, OnStateChangedListener listener) {
|
||||
if (mSharedPreferences.contains(key)) {
|
||||
listener.initState(mSharedPreferences.getBoolean(key, false));
|
||||
}
|
||||
}
|
||||
|
||||
private List<OnStateChangedListener> getListenerListOrCreateIfNotExists(String key) {
|
||||
List<OnStateChangedListener> listeners = mKeyStateListenersMap.get(key);
|
||||
if (listeners == null) {
|
||||
listeners = new CopyOnWriteArrayList<>();
|
||||
mKeyStateListenersMap.put(key, listeners);
|
||||
}
|
||||
return listeners;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
26
common/src/main/java/com/stardust/util/ViewUtil.java
Normal file
26
common/src/main/java/com/stardust/util/ViewUtil.java
Normal file
@@ -0,0 +1,26 @@
|
||||
package com.stardust.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.IdRes;
|
||||
import android.view.View;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/24.
|
||||
*/
|
||||
|
||||
public class ViewUtil {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <V extends View> V $(View view, @IdRes int resId) {
|
||||
return (V) view.findViewById(resId);
|
||||
}
|
||||
|
||||
public static int getStatusBarHeight(Context context) {
|
||||
int result = 0;
|
||||
int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
|
||||
if (resourceId > 0) {
|
||||
result = context.getResources().getDimensionPixelSize(resourceId);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
3
common/src/main/res/values/strings.xml
Normal file
3
common/src/main/res/values/strings.xml
Normal file
@@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<string name="app_name">common</string>
|
||||
</resources>
|
||||
17
common/src/test/java/com/stardust/ExampleUnitTest.java
Normal file
17
common/src/test/java/com/stardust/ExampleUnitTest.java
Normal file
@@ -0,0 +1,17 @@
|
||||
package com.stardust;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
public class ExampleUnitTest {
|
||||
@Test
|
||||
public void addition_isCorrect() throws Exception {
|
||||
assertEquals(4, 2 + 2);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user