Refactor: split into modules autojs, common, app and automator

This commit is contained in:
hyb1996
2017-04-03 00:43:15 +08:00
parent e7500e6e21
commit bfabef6a0e
182 changed files with 2521 additions and 5840 deletions

1
common/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/build

32
common/build.gradle Normal file
View 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
View 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

View File

@@ -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());
}
}

View 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>

View 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();
}
}

View 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);
}
}
}

View File

@@ -0,0 +1,15 @@
package com.stardust.pio;
/**
* Created by Stardust on 2017/4/1.
*/
public class PWritableFile extends PFile {
public PWritableFile(){
}
}

View File

@@ -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);
}
}

View 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;
}
}

View File

@@ -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;
}
}
}

View 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));
}
}

View File

@@ -0,0 +1,11 @@
package com.stardust.util;
/**
* Created by Stardust on 2017/3/10.
*/
public interface Consumer<T> {
void accept(T t);
}

View 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);
}
}
}

View 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();
}
}

View File

@@ -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;
}
}

View 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());
}
}

View 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"));
}
}
}

View 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;
}
}

View 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;
}
}

View 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);
}
}

View File

@@ -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;
}
}

View 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;
}
}

View 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;
}
}

View File

@@ -0,0 +1,3 @@
<resources>
<string name="app_name">common</string>
</resources>

View 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);
}
}