diff --git a/Android/adb/libs/AdbLib.jar b/Android/adb/libs/AdbLib.jar deleted file mode 100644 index 26aa7eefb526c9f1290979a5702dbf5d60fd3bb8..0000000000000000000000000000000000000000 Binary files a/Android/adb/libs/AdbLib.jar and /dev/null differ diff --git a/Android/adb/src/androidTest/java/com/didichuxing/doraemonkit/adb/ExampleInstrumentedTest.java b/Android/adb/src/androidTest/java/com/didichuxing/doraemonkit/adb/ExampleInstrumentedTest.java deleted file mode 100644 index b02c5a228ef9888385abd51f0f0ec02e95b02a0c..0000000000000000000000000000000000000000 --- a/Android/adb/src/androidTest/java/com/didichuxing/doraemonkit/adb/ExampleInstrumentedTest.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.didichuxing.doraemonkit.adb; - -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.*; - -/** - * Instrumented test, which will execute on an Android device. - * - * @see Testing documentation - */ -@RunWith(AndroidJUnit4.class) -public class ExampleInstrumentedTest { - @Test - public void useAppContext() throws Exception { - // Context of the app under test. - Context appContext = InstrumentationRegistry.getTargetContext(); - - assertEquals("com.didichuxing.doraemonkit.adb.test", appContext.getPackageName()); - } -} diff --git a/Android/adb/src/main/AndroidManifest.xml b/Android/adb/src/main/AndroidManifest.xml deleted file mode 100644 index 36d28b18e610b698579af7f764a9288c4b952756..0000000000000000000000000000000000000000 --- a/Android/adb/src/main/AndroidManifest.xml +++ /dev/null @@ -1 +0,0 @@ - diff --git a/Android/adb/src/main/java/com/didichuxing/doraemonkit/adb/AdbConnector.java b/Android/adb/src/main/java/com/didichuxing/doraemonkit/adb/AdbConnector.java deleted file mode 100644 index 1048a47c9249a3e85694954bdcbdd37ae85ba226..0000000000000000000000000000000000000000 --- a/Android/adb/src/main/java/com/didichuxing/doraemonkit/adb/AdbConnector.java +++ /dev/null @@ -1,119 +0,0 @@ -package com.didichuxing.doraemonkit.adb; - -import android.content.Context; -import android.util.Base64; -import android.util.Log; - -import com.cgutman.adblib.AdbBase64; -import com.cgutman.adblib.AdbConnection; -import com.cgutman.adblib.AdbCrypto; -import com.cgutman.adblib.AdbStream; - -import java.io.File; -import java.io.IOException; -import java.net.Socket; -import java.security.NoSuchAlgorithmException; -import java.security.spec.InvalidKeySpecException; - -/** - * Created by yangmenglin on 2018/11/1. - */ - -public class AdbConnector { - private static final String TAG = "AdbConnector"; - private AdbConnection connection; - private AdbStream stream; - - private AdbBase64 getBase64Impl() { - return new AdbBase64() { - @Override - public String encodeToString(byte[] data) { - return Base64.encodeToString(data, Base64.DEFAULT); - } - }; - } - - // This function loads a keypair from the specified files if one exists, and if not, - // it creates a new keypair and saves it in the specified files - private AdbCrypto setupCrypto(String pubKeyFile, String privKeyFile) - throws NoSuchAlgorithmException, InvalidKeySpecException, IOException { - File pub = new File(pubKeyFile); - File priv = new File(privKeyFile); - AdbCrypto c = null; - - // Try to load a key pair from the files - if (pub.exists() && priv.exists()) { - try { - c = AdbCrypto.loadAdbKeyPair(getBase64Impl(), priv, pub); - } catch (Exception e) { - // Failed to read from file - c = null; - } - } - - if (c == null) { - // We couldn't load a key, so let's generate a new one - c = AdbCrypto.generateAdbKeyPair(getBase64Impl()); - - // Save it - c.saveAdbKeyPair(priv, pub); - Log.d(TAG, "Generated new keypair"); - } else { - Log.d(TAG, "Loaded existing keypair"); - } - - return c; - } - - - private AdbConnection connection(Context context) throws Exception { - - // Setup the crypto object required for the AdbConnection - String path = context.getCacheDir().getAbsolutePath(); - Log.d(TAG, "connection path " + path); - AdbCrypto crypto = setupCrypto(path + File.separatorChar + "pub.key", - path + File.separatorChar + "priv.key"); - - Log.e(TAG, "Socket connecting..."); - Socket sock = new Socket(AdbConstant.HOST, AdbConstant.PORT); - // Connect the socket to the remote host - - Log.e(TAG, "Socket connected"); - - // Construct the AdbConnection object - - AdbConnection adb = AdbConnection.create(sock, crypto); - - // Start the application layer connection process - Log.e(TAG, "ADB connecting..."); - - adb.connect(); - - Log.e(TAG, "ADB connected"); - - - return adb; - } - - - public String openShell(Context context,String cmd) throws Exception { - if (connection == null) { - connection = connection(context); - } - stream = connection.open(cmd); - StringBuilder stringBuilder = new StringBuilder(); - byte[] bytes = stream.read(); - stringBuilder.append(new String(bytes)); - while (bytes != null) { - stringBuilder.append(new String(bytes)); - try { - bytes = stream.read(); - } catch (Exception e) { - bytes = null; - Log.d("morning", e.getMessage()); - } - } - Log.d("morning", "length is " + stringBuilder.length()); - return stringBuilder.toString(); - } -} diff --git a/Android/adb/src/main/java/com/didichuxing/doraemonkit/adb/AdbConstant.java b/Android/adb/src/main/java/com/didichuxing/doraemonkit/adb/AdbConstant.java deleted file mode 100644 index 7b669be11f9f118d4bed05256e2f6ce22c6f3f50..0000000000000000000000000000000000000000 --- a/Android/adb/src/main/java/com/didichuxing/doraemonkit/adb/AdbConstant.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.didichuxing.doraemonkit.adb; - -/** - * Created by yangmenglin on 2018/11/1. - */ - -public class AdbConstant { - public static final String HOST = "127.0.0.1"; - public static final int PORT = 5555; -} diff --git a/Android/adb/src/main/java/com/didichuxing/doraemonkit/adb/AdbManager.java b/Android/adb/src/main/java/com/didichuxing/doraemonkit/adb/AdbManager.java deleted file mode 100644 index 9269bf04094a8cb6dab367d21dec102d5d7191f1..0000000000000000000000000000000000000000 --- a/Android/adb/src/main/java/com/didichuxing/doraemonkit/adb/AdbManager.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.didichuxing.doraemonkit.adb; - -import android.content.Context; - -/** - * Created by yangmenglin on 2018/11/1. - */ - -public class AdbManager { - static class Holder { - private static AdbManager INSTANCE = new AdbManager(); - } - private AdbService adbService; - - public static AdbManager getInstance() { - return Holder.INSTANCE; - } - - public void init(Context context) { - if (adbService == null) { - adbService = new AdbService(context); - } - } - - private AdbManager() { - } - - public void performAdbRequest(String cmd,Callback callback){ - adbService.performAdbRequest(cmd,callback); - } -} diff --git a/Android/adb/src/main/java/com/didichuxing/doraemonkit/adb/AdbService.java b/Android/adb/src/main/java/com/didichuxing/doraemonkit/adb/AdbService.java deleted file mode 100644 index 88e0fdb21765690ff7c70c30d4f69f6f43cf17c2..0000000000000000000000000000000000000000 --- a/Android/adb/src/main/java/com/didichuxing/doraemonkit/adb/AdbService.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.didichuxing.doraemonkit.adb; - -import android.content.Context; -import android.text.TextUtils; - -/** - * Created by yangmenglin on 2018/11/1. - */ - -public class AdbService { - private ThreadPoolProxy mProxy; - private AdbConnector mAdbConnector; - private Context mContext; - public AdbService(Context context){ - mProxy = ThreadPoolProxyFactory.getThreadPoolProxy(); - mAdbConnector = new AdbConnector(); - mContext = context; - } - public void performAdbRequest(final String cmd, final Callback callback) { - Runnable runnable = new Runnable() { - @Override - public void run() { - try { - String response = mAdbConnector.openShell(mContext, cmd); - if (!TextUtils.isEmpty(response)) { - if (callback != null) { - callback.onSuccess(response); - } - } else { - if (callback != null) { - callback.onFail(""); - } - } - } catch (Exception e) { - if (callback != null) { - callback.onFail(e.getMessage()); - } - } - } - }; - mProxy.execute(runnable); - } - - -} diff --git a/Android/adb/src/main/java/com/didichuxing/doraemonkit/adb/Callback.java b/Android/adb/src/main/java/com/didichuxing/doraemonkit/adb/Callback.java deleted file mode 100644 index f283d3d2215a59b3a77aed61528f56bbc6da54d2..0000000000000000000000000000000000000000 --- a/Android/adb/src/main/java/com/didichuxing/doraemonkit/adb/Callback.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.didichuxing.doraemonkit.adb; - -/** - * Created by yangmenglin on 2018/11/1. - */ - -public interface Callback { - void onSuccess(String adbResponse); - void onFail(String failString); -} diff --git a/Android/adb/src/main/java/com/didichuxing/doraemonkit/adb/ThreadPoolProxy.java b/Android/adb/src/main/java/com/didichuxing/doraemonkit/adb/ThreadPoolProxy.java deleted file mode 100644 index dbb26bf798cbf7c1a7e2f0b4d22e9cda350ae0a8..0000000000000000000000000000000000000000 --- a/Android/adb/src/main/java/com/didichuxing/doraemonkit/adb/ThreadPoolProxy.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.didichuxing.doraemonkit.adb; - -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.LinkedBlockingDeque; -import java.util.concurrent.RejectedExecutionHandler; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -public class ThreadPoolProxy { - - ThreadPoolExecutor mExecutor; - private int mCorePoolSize; - private int mMaximumPoolSize; - - - /** - * @param corePoolSize 核心池的大小 - * @param maximumPoolSize 最大线程数 - */ - public ThreadPoolProxy(int corePoolSize, int maximumPoolSize) { - mCorePoolSize = corePoolSize; - mMaximumPoolSize = maximumPoolSize; - } - - /** - * 初始化ThreadPoolExecutor - * 双重检查加锁,只有在第一次实例化的时候才启用同步机制,提高了性能 - */ - private void initThreadPoolExecutor() { - if (mExecutor == null || mExecutor.isShutdown() || mExecutor.isTerminated()) { - synchronized (ThreadPoolProxy.class) { - if (mExecutor == null || mExecutor.isShutdown() || mExecutor.isTerminated()) { - long keepAliveTime = 3000; - TimeUnit unit = TimeUnit.MILLISECONDS; - BlockingQueue workQueue = new LinkedBlockingDeque<>(); - ThreadFactory threadFactory = Executors.defaultThreadFactory(); - RejectedExecutionHandler handler = new ThreadPoolExecutor.DiscardPolicy(); - - mExecutor = new ThreadPoolExecutor(mCorePoolSize, mMaximumPoolSize, keepAliveTime, unit, workQueue, - threadFactory, handler); - } - } - } - } - /** - 执行任务和提交任务的区别? - 1.有无返回值 - execute->没有返回值 - submit-->有返回值 - 2.Future的具体作用? - 1.有方法可以接收一个任务执行完成之后的结果,其实就是get方法,get方法是一个阻塞方法 - 2.get方法的签名抛出了异常===>可以处理任务执行过程中可能遇到的异常 - */ - /** - * 执行任务 - */ - public void execute(Runnable task) { - initThreadPoolExecutor(); - mExecutor.execute(task); - } - - /** - * 提交任务 - */ - public Future submit(Runnable task) { - initThreadPoolExecutor(); - return mExecutor.submit(task); - } - - /** - * 移除任务 - */ - public void remove(Runnable task) { - initThreadPoolExecutor(); - mExecutor.remove(task); - } -} \ No newline at end of file diff --git a/Android/adb/src/main/java/com/didichuxing/doraemonkit/adb/ThreadPoolProxyFactory.java b/Android/adb/src/main/java/com/didichuxing/doraemonkit/adb/ThreadPoolProxyFactory.java deleted file mode 100644 index 580d45a1f3f77557eb72dd32168d9ec032d9d59b..0000000000000000000000000000000000000000 --- a/Android/adb/src/main/java/com/didichuxing/doraemonkit/adb/ThreadPoolProxyFactory.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.didichuxing.doraemonkit.adb; - -public class ThreadPoolProxyFactory { - private static ThreadPoolProxy mThreadPoolProxy; - - public static ThreadPoolProxy getThreadPoolProxy() { - if (mThreadPoolProxy == null) { - synchronized (ThreadPoolProxyFactory.class) { - if (mThreadPoolProxy == null) { - mThreadPoolProxy = new ThreadPoolProxy(5, 5); - } - } - } - return mThreadPoolProxy; - } -} \ No newline at end of file diff --git a/Android/adb/src/main/res/values/strings.xml b/Android/adb/src/main/res/values/strings.xml deleted file mode 100644 index 8542005550c7c87f5b6679a433515d5f43cd921a..0000000000000000000000000000000000000000 --- a/Android/adb/src/main/res/values/strings.xml +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/Android/adb/src/test/java/com/didichuxing/doraemonkit/adb/ExampleUnitTest.java b/Android/adb/src/test/java/com/didichuxing/doraemonkit/adb/ExampleUnitTest.java deleted file mode 100644 index 0083d711f2d76871b903f2eed9ea6a857d3e72c5..0000000000000000000000000000000000000000 --- a/Android/adb/src/test/java/com/didichuxing/doraemonkit/adb/ExampleUnitTest.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.didichuxing.doraemonkit.adb; - -import org.junit.Test; - -import static org.junit.Assert.*; - -/** - * Example local unit test, which will execute on the development machine (host). - * - * @see Testing documentation - */ -public class ExampleUnitTest { - @Test - public void addition_isCorrect() throws Exception { - assertEquals(4, 2 + 2); - } -} \ No newline at end of file diff --git a/Android/adb/upload.gradle b/Android/adb/upload.gradle deleted file mode 100644 index 9435c3c942033078d71367a074c7a1f3c5db3bbc..0000000000000000000000000000000000000000 --- a/Android/adb/upload.gradle +++ /dev/null @@ -1,15 +0,0 @@ -apply plugin: 'com.novoda.bintray-release' -// 配置发布 -publish { - def groupProjectID = 'com.didichuxing.doraemonkit' - def artifactProjectID = 'adb' - def publishVersionID = '1.0.0' - - userOrg = 'doraemonkit' - repoName = 'DoraemonKit' - groupId = groupProjectID - artifactId = artifactProjectID - publishVersion = publishVersionID - desc = '{library description}' - website = '{github_url}' -} \ No newline at end of file diff --git a/Android/app/build.gradle b/Android/app/build.gradle index aa154eccbe5f7b160c71d27081efafa763a3fee4..fe75a46a35cba35594db6d7a69aecb8a4e258ad5 100644 --- a/Android/app/build.gradle +++ b/Android/app/build.gradle @@ -2,18 +2,27 @@ apply plugin: 'com.android.application' apply from: 'doraemonkit.gradle' android { - compileSdkVersion 26 + compileSdkVersion 27 defaultConfig { applicationId "com.didichuxing.doraemondemo" minSdkVersion 16 targetSdkVersion 27 versionCode 1 versionName "1.0" - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } + signingConfigs { + release { + storeFile file("keystore/test.keystore") + storePassword "test123456" + keyAlias "test" + keyPassword "test123456" + } } buildTypes { release { - minifyEnabled false + minifyEnabled true + shrinkResources true + signingConfig signingConfigs.release proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } @@ -21,13 +30,11 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation 'com.android.support:appcompat-v7:26.1.0' + implementation 'com.android.support:appcompat-v7:27.1.0' implementation 'com.android.support.constraint:constraint-layout:1.1.3' implementation project(':doraemonkit') // implementation 'com.didichuxing.doraemonkit:doraemonkit:1.0.0' - testImplementation 'junit:junit:4.12' - androidTestImplementation 'com.android.support.test:runner:1.0.2' - androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' implementation 'com.squareup.okhttp3:okhttp:3.12.1' implementation 'com.squareup.okio:okio:1.15.0' + } diff --git a/Android/app/doraemonkit.gradle b/Android/app/doraemonkit.gradle index 4c3f1c5501bbc83e16ac28d8f940e0529fcf0700..f580511e7b5dd2cc33e0cd1e1fb5753ff152b933 100644 --- a/Android/app/doraemonkit.gradle +++ b/Android/app/doraemonkit.gradle @@ -9,6 +9,7 @@ if (applyPlugin) { // 这里引用正常库 dependencies { implementation project(":doraemonkit") + implementation project(":doraemonkit-aop") } } else { // 引用no-op的库 diff --git a/Android/app/keystore/test.keystore b/Android/app/keystore/test.keystore new file mode 100644 index 0000000000000000000000000000000000000000..850e1cce53cda8b46323a20155f4fb914b8dc7bf Binary files /dev/null and b/Android/app/keystore/test.keystore differ diff --git a/Android/app/src/main/java/com/didichuxing/doraemondemo/App.java b/Android/app/src/main/java/com/didichuxing/doraemondemo/App.java index 7da5a8a8127253ee752a4b71efe5dafa0b52cf32..3e76aa90b2a9fa0a04885b6c4066c35e856f6aa3 100644 --- a/Android/app/src/main/java/com/didichuxing/doraemondemo/App.java +++ b/Android/app/src/main/java/com/didichuxing/doraemondemo/App.java @@ -1,12 +1,9 @@ package com.didichuxing.doraemondemo; import android.app.Application; -import android.content.Context; -import android.content.Intent; import android.os.StrictMode; import com.didichuxing.doraemonkit.DoraemonKit; -import com.didichuxing.doraemonkit.kit.webdoor.WebDoorManager; /** * Created by zhangweida on 2018/6/22. diff --git a/Android/compiler-plugin/build.gradle b/Android/compiler-plugin/build.gradle deleted file mode 100644 index 3e0637db695251c4ddeaffa6d8ac61140e711be9..0000000000000000000000000000000000000000 --- a/Android/compiler-plugin/build.gradle +++ /dev/null @@ -1,13 +0,0 @@ -apply plugin: 'groovy' -apply from: 'upload.gradle' - -targetCompatibility = JavaVersion.VERSION_1_7 -sourceCompatibility = JavaVersion.VERSION_1_7 - -dependencies { - compile gradleApi() - compile localGroovy() - compile 'com.android.tools.build:gradle:3.0.1' - compile 'org.aspectj:aspectjtools:1.8.6' - compile 'org.aspectj:aspectjrt:1.8.6' -} \ No newline at end of file diff --git a/Android/compiler-plugin/src/main/groovy/didichuxing/doraemon/plugin/DoraemonPlugin.groovy b/Android/compiler-plugin/src/main/groovy/didichuxing/doraemon/plugin/DoraemonPlugin.groovy deleted file mode 100644 index a2d5836cd960d6415ef11a7417a6da179987121f..0000000000000000000000000000000000000000 --- a/Android/compiler-plugin/src/main/groovy/didichuxing/doraemon/plugin/DoraemonPlugin.groovy +++ /dev/null @@ -1,68 +0,0 @@ -package didichuxing.doraemon.plugin - -import com.android.build.gradle.AppPlugin -import com.android.build.gradle.LibraryPlugin -import org.aspectj.bridge.IMessage -import org.aspectj.bridge.MessageHandler -import org.aspectj.tools.ajc.Main -import org.gradle.api.Plugin -import org.gradle.api.Project -import org.gradle.api.tasks.compile.JavaCompile - -class DoraemonPlugin implements Plugin { - @Override void apply(Project project) { - def hasApp = project.plugins.withType(AppPlugin) - def hasLib = project.plugins.withType(LibraryPlugin) - if (!hasApp && !hasLib) { - throw new IllegalStateException("'android' or 'android-library' plugin required.") - } - - final def log = project.logger - final def variants - if (hasApp) { - variants = project.android.applicationVariants - } else { - variants = project.android.libraryVariants - } - project.dependencies { - implementation 'org.aspectj:aspectjrt:1.8.6' - } - - variants.all { variant -> - JavaCompile javaCompile = variant.javaCompile - javaCompile.doLast { - String[] args = [ - "-showWeaveInfo", - "-1.5", - "-inpath", javaCompile.destinationDir.toString(), - "-aspectpath", javaCompile.classpath.asPath, - "-d", javaCompile.destinationDir.toString(), - "-classpath", javaCompile.classpath.asPath, - "-bootclasspath", project.android.bootClasspath.join(File.pathSeparator) - ] - log.debug "ajc args: " + Arrays.toString(args) - - MessageHandler handler = new MessageHandler(true) - new Main().run(args, handler) - for (IMessage message : handler.getMessages(null, true)) { - switch (message.getKind()) { - case IMessage.ABORT: - case IMessage.ERROR: - case IMessage.FAIL: - log.error message.message, message.thrown - break - case IMessage.WARNING: - log.warn message.message, message.thrown - break - case IMessage.INFO: - log.info message.message, message.thrown - break - case IMessage.DEBUG: - log.debug message.message, message.thrown - break - } - } - } - } - } -} diff --git a/Android/compiler-plugin/src/main/resources/META-INF/gradle-plugins/com.doraemon.compiler.plugin.properties b/Android/compiler-plugin/src/main/resources/META-INF/gradle-plugins/com.doraemon.compiler.plugin.properties deleted file mode 100644 index c988f9188b166615cf48992f782ecdfd6d26493c..0000000000000000000000000000000000000000 --- a/Android/compiler-plugin/src/main/resources/META-INF/gradle-plugins/com.doraemon.compiler.plugin.properties +++ /dev/null @@ -1 +0,0 @@ -implementation-class=didichuxing.doraemon.plugin.DoraemonPlugin diff --git a/Android/adb/.gitignore b/Android/doraemonkit-aop/.gitignore similarity index 100% rename from Android/adb/.gitignore rename to Android/doraemonkit-aop/.gitignore diff --git a/Android/adb/build.gradle b/Android/doraemonkit-aop/build.gradle similarity index 62% rename from Android/adb/build.gradle rename to Android/doraemonkit-aop/build.gradle index aad254c70e7b58fbdd96a1926c5aa3719a1b469a..69f5c8def6c24194e34e46b99bd86a1c6bd42ad1 100644 --- a/Android/adb/build.gradle +++ b/Android/doraemonkit-aop/build.gradle @@ -4,16 +4,14 @@ apply from: 'upload.gradle' android { compileSdkVersion 26 - - defaultConfig { - minSdkVersion 15 + minSdkVersion 16 targetSdkVersion 26 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" - + javaCompileOptions { annotationProcessorOptions { includeCompileClasspath = true } } } buildTypes { @@ -27,10 +25,7 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) - - implementation 'com.android.support:appcompat-v7:26.1.0' - testImplementation 'junit:junit:4.12' - androidTestImplementation 'com.android.support.test:runner:1.0.2' - androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' - implementation files('libs/AdbLib.jar') + compileOnly project(":doraemonkit") + compileOnly 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.4' + compileOnly 'com.squareup.okhttp3:okhttp:3.12.1' } diff --git a/Android/adb/proguard-rules.pro b/Android/doraemonkit-aop/proguard-rules.pro similarity index 100% rename from Android/adb/proguard-rules.pro rename to Android/doraemonkit-aop/proguard-rules.pro diff --git a/Android/doraemonkit-aop/src/main/AndroidManifest.xml b/Android/doraemonkit-aop/src/main/AndroidManifest.xml new file mode 100644 index 0000000000000000000000000000000000000000..cc7fb5d38cd59fed24f1e555353958425e68353c --- /dev/null +++ b/Android/doraemonkit-aop/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/aspect/AopUtils.java b/Android/doraemonkit-aop/src/main/java/parking/didi/com/aop/AopUtils.java similarity index 96% rename from Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/aspect/AopUtils.java rename to Android/doraemonkit-aop/src/main/java/parking/didi/com/aop/AopUtils.java index 09de129374cc886d20daaf0e3e36b3452bff62ae..b433a67acdddf01820b722383ad445173748bc34 100644 --- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/aspect/AopUtils.java +++ b/Android/doraemonkit-aop/src/main/java/parking/didi/com/aop/AopUtils.java @@ -1,4 +1,4 @@ -package com.didichuxing.doraemonkit.kit.network.aspect; +package parking.didi.com.aop; import com.didichuxing.doraemonkit.kit.network.NetworkManager; import com.didichuxing.doraemonkit.kit.network.httpurlconnection.HttpUrlConnectionProxy; diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/DoraemonHooker.java b/Android/doraemonkit-aop/src/main/java/parking/didi/com/aop/DoraemonHooker.java similarity index 92% rename from Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/DoraemonHooker.java rename to Android/doraemonkit-aop/src/main/java/parking/didi/com/aop/DoraemonHooker.java index d7cb3cc8586498651ad9c5f7b6082d7456cc1b81..4294845c3d52bf7a38122b3c077738677459edd3 100644 --- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/DoraemonHooker.java +++ b/Android/doraemonkit-aop/src/main/java/parking/didi/com/aop/DoraemonHooker.java @@ -1,7 +1,8 @@ -package com.didichuxing.doraemonkit; +package parking.didi.com.aop; import android.app.Application; +import com.didichuxing.doraemonkit.DoraemonKit; import com.didichuxing.doraemonkit.kit.timecounter.TimeCounterManager; import com.didichuxing.doraemonkit.util.LogHelper; diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/aspect/HttpUrlAspect.java b/Android/doraemonkit-aop/src/main/java/parking/didi/com/aop/HttpUrlAspect.java similarity index 90% rename from Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/aspect/HttpUrlAspect.java rename to Android/doraemonkit-aop/src/main/java/parking/didi/com/aop/HttpUrlAspect.java index 545b3cf96c811a383a6b42250ccfa78b798aba95..4988bf3630c2e3bc8608bac76450e97e83596f54 100644 --- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/aspect/HttpUrlAspect.java +++ b/Android/doraemonkit-aop/src/main/java/parking/didi/com/aop/HttpUrlAspect.java @@ -1,4 +1,4 @@ -package com.didichuxing.doraemonkit.kit.network.aspect; +package parking.didi.com.aop; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/aspect/OkHttpAspect.java b/Android/doraemonkit-aop/src/main/java/parking/didi/com/aop/OkHttpAspect.java similarity index 88% rename from Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/aspect/OkHttpAspect.java rename to Android/doraemonkit-aop/src/main/java/parking/didi/com/aop/OkHttpAspect.java index d5b966d5e4dd2c8e294bf797ee55059860e62960..00ded2b97f57327709e5eb94ac6fdc7cedc34b5e 100644 --- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/aspect/OkHttpAspect.java +++ b/Android/doraemonkit-aop/src/main/java/parking/didi/com/aop/OkHttpAspect.java @@ -1,4 +1,4 @@ -package com.didichuxing.doraemonkit.kit.network.aspect; +package parking.didi.com.aop; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.After; diff --git a/Android/doraemonkit-aop/src/main/res/values/strings.xml b/Android/doraemonkit-aop/src/main/res/values/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..ba530362aa33065b52c1f2a309f3c4dab4489476 --- /dev/null +++ b/Android/doraemonkit-aop/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + doraemonkit_aop + diff --git a/Android/doraemonkit-aop/upload.gradle b/Android/doraemonkit-aop/upload.gradle new file mode 100644 index 0000000000000000000000000000000000000000..7510e9b057303888c281ca59919c272fb9b637ab --- /dev/null +++ b/Android/doraemonkit-aop/upload.gradle @@ -0,0 +1,15 @@ +apply plugin: 'com.novoda.bintray-release' +// 配置发布 +publish { + def groupProjectID = 'com.didichuxing.doraemonkit' + def artifactProjectID = 'doraemonkit-aop' + def publishVersionID = '1.0.0' + + userOrg = 'doraemonkit' + repoName = 'DoraemonKit' + groupId = groupProjectID + artifactId = artifactProjectID + publishVersion = publishVersionID + desc = '{library description}' + website = '{github_url}' +} \ No newline at end of file diff --git a/Android/adb/upload.sh b/Android/doraemonkit-aop/upload.sh similarity index 100% rename from Android/adb/upload.sh rename to Android/doraemonkit-aop/upload.sh diff --git a/Android/doraemonkit-no-op/upload.gradle b/Android/doraemonkit-no-op/upload.gradle index 8aa3c5b59ef6100e2c082f74fbc7c96e13f95591..83803fd777f7dde37aa493a7ff48a13cd3bc981e 100644 --- a/Android/doraemonkit-no-op/upload.gradle +++ b/Android/doraemonkit-no-op/upload.gradle @@ -3,7 +3,7 @@ apply plugin: 'com.novoda.bintray-release' publish { def groupProjectID = 'com.didichuxing.doraemonkit' def artifactProjectID = 'doraemonkit-no-op' - def publishVersionID = '1.1.7' + def publishVersionID = '1.1.8' userOrg = 'doraemonkit' repoName = 'DoraemonKit' diff --git a/Android/doraemonkit/build.gradle b/Android/doraemonkit/build.gradle index 579d2c894e005d12530ec3686c6161e11b836fb7..0cb8f17fb81ceadabef5769804744e8d337b16e1 100644 --- a/Android/doraemonkit/build.gradle +++ b/Android/doraemonkit/build.gradle @@ -37,10 +37,11 @@ dependencies { } implementation 'com.squareup.okhttp3:okhttp:3.12.1' compileOnly 'com.squareup.okio:okio:1.15.0' - compileOnly 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.4' testImplementation 'junit:junit:4.12' implementation 'com.google.code.gson:gson:2.8.2' implementation 'com.google.zxing:core:3.3.0' + // Android P禁用hide api,这个库可以支持hide api的反射访问 + implementation 'me.weishu:free_reflection:2.0.0' } diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/DoraemonKit.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/DoraemonKit.java index 00f0a1dd00369c0f81795044cc6928fd60ffdce2..368e169adfd821910ff2f156b24185a42de6205d 100644 --- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/DoraemonKit.java +++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/DoraemonKit.java @@ -13,7 +13,7 @@ import com.didichuxing.doraemonkit.kit.IKit; import com.didichuxing.doraemonkit.kit.alignruler.AlignRuler; import com.didichuxing.doraemonkit.kit.blockmonitor.BlockMonitorKit; import com.didichuxing.doraemonkit.kit.colorpick.ColorPicker; -import com.didichuxing.doraemonkit.kit.crash.Crash; +import com.didichuxing.doraemonkit.kit.crash.CrashCapture; import com.didichuxing.doraemonkit.kit.custom.Custom; import com.didichuxing.doraemonkit.kit.dataclean.DataClean; import com.didichuxing.doraemonkit.kit.fileexplorer.FileExplorer; @@ -29,6 +29,7 @@ import com.didichuxing.doraemonkit.kit.parameter.ram.Ram; import com.didichuxing.doraemonkit.kit.sysinfo.SysInfo; import com.didichuxing.doraemonkit.kit.temporaryclose.TemporaryClose; import com.didichuxing.doraemonkit.kit.timecounter.TimeCounterKit; +import com.didichuxing.doraemonkit.kit.timecounter.instrumentation.HandlerHooker; import com.didichuxing.doraemonkit.kit.viewcheck.ViewChecker; import com.didichuxing.doraemonkit.kit.weaknetwork.WeakNetwork; import com.didichuxing.doraemonkit.kit.webdoor.WebDoor; @@ -89,6 +90,7 @@ public class DoraemonKit { return; } sHasInit = true; + HandlerHooker.doHook(app); ServiceHookManager.getInstance().install(); app.registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() { int startedActivityCounts; @@ -160,7 +162,7 @@ public class DoraemonKit { tool.add(new GpsMock()); } tool.add(new WebDoor()); - tool.add(new Crash()); + tool.add(new CrashCapture()); tool.add(new LogInfo()); tool.add(new DataClean()); tool.add(new WeakNetwork()); diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/config/CrashCaptureConfig.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/config/CrashCaptureConfig.java index c6e188a7ab5d28b1f61aa0320bae73254cbaec01..8f8dc36028d8f00c8e62a6f96de850711b6249a9 100644 --- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/config/CrashCaptureConfig.java +++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/config/CrashCaptureConfig.java @@ -1,17 +1,17 @@ package com.didichuxing.doraemonkit.config; import android.content.Context; +import android.os.Environment; import com.didichuxing.doraemonkit.constant.SharedPrefsKey; import com.didichuxing.doraemonkit.util.SharedPrefsUtil; public class CrashCaptureConfig { - public static boolean isCrashCaptureOpen(Context context) { - return SharedPrefsUtil.getBoolean(context, SharedPrefsKey.CRASH_OPEN, false); + return SharedPrefsUtil.getBoolean(context, SharedPrefsKey.CRASH_CAPTURE_OPEN, false); } public static void setCrashCaptureOpen(Context context, boolean open) { - SharedPrefsUtil.putBoolean(context, SharedPrefsKey.CRASH_OPEN, open); + SharedPrefsUtil.putBoolean(context, SharedPrefsKey.CRASH_CAPTURE_OPEN, open); } } diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/constant/BundleKey.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/constant/BundleKey.java index e388d6000b743347dc03370815e4a984e0bb4a97..48e0bbb7c20f7857744666f54c1bafb0a2b712d1 100644 --- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/constant/BundleKey.java +++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/constant/BundleKey.java @@ -8,7 +8,6 @@ public interface BundleKey { String FILE_KEY = "file_key"; String FRAGMENT_INDEX = "fragment_index"; String ACCESSIBILITY_DATA = "accessibility_data"; - String PERFORMANCE_TYPE = "PERFORMANCE_TYPE"; - + String PERFORMANCE_TYPE = "performance_type"; String KEY_URL = "key_url"; } \ No newline at end of file diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/constant/CachesKey.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/constant/CachesKey.java index bf28cc3c5b1c185c025df127623bbe5c539c028c..82bb54184299f86e44959cbac445b521d7065a94 100644 --- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/constant/CachesKey.java +++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/constant/CachesKey.java @@ -6,4 +6,5 @@ package com.didichuxing.doraemonkit.constant; public interface CachesKey { String WEB_DOOR_HISTORY = "web_door_history"; + String CRASH_HISTORY = "crash"; } \ No newline at end of file diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/constant/SharedPrefsKey.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/constant/SharedPrefsKey.java index 4d9854d76333e5cb89310f835e1a5cc3ef5c5595..1d7ee26cb3ab5ca0f08ee890cb6aa0b521f0f730 100644 --- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/constant/SharedPrefsKey.java +++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/constant/SharedPrefsKey.java @@ -10,7 +10,7 @@ public interface SharedPrefsKey { String FRAME_INFO_MEMORY_OPEN = "frame_info_memory_open"; String FRAME_INFO_TRAFFIC_OPEN = "frame_info_traffic_open"; String GPS_MOCK_OPEN = "gps_mock_open"; - String CRASH_OPEN = "crash_open"; + String CRASH_CAPTURE_OPEN = "crash_capture_open"; String FLOAT_ICON_POS_X = "float_icon_pos_x"; String FLOAT_ICON_POS_Y = "float_icon_pos_y"; String LOG_INFO_OPEN = "log_info_open"; diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/common/PerformanceDataManager.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/common/PerformanceDataManager.java index 49a2de5507fe6a0527c2077b519e3c98f1524390..8be5222a1d65fedfb5783a532f5e7956d8991e60 100644 --- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/common/PerformanceDataManager.java +++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/common/PerformanceDataManager.java @@ -15,10 +15,10 @@ import android.text.TextUtils; import android.text.format.DateUtils; import android.view.Choreographer; -import com.didichuxing.doraemonkit.R; +import com.didichuxing.doraemonkit.DoraemonKit; import com.didichuxing.doraemonkit.config.PerformanceInfoConfig; -import com.didichuxing.doraemonkit.kit.custom.PerformanceInfo; import com.didichuxing.doraemonkit.kit.custom.UploadMonitorInfoBean; +import com.didichuxing.doraemonkit.kit.custom.UploadMonitorItem; import com.didichuxing.doraemonkit.kit.network.NetworkManager; import com.didichuxing.doraemonkit.util.FileManager; import com.didichuxing.doraemonkit.util.JsonUtil; @@ -54,6 +54,10 @@ public class PerformanceDataManager { private int mLastSkippedFrames; private float mLastCpuRate; private float mLastMemoryInfo; + private long mUpBytes; + private long mDownBytes; + private long mLastUpBytes; + private long mLastDownBytes; private Handler mHandler; private HandlerThread mHandlerThread; private float mMaxMemory; @@ -67,6 +71,7 @@ public class PerformanceDataManager { private static final int MSG_CPU = 1; private static final int MSG_MEMORY = 2; private static final int MSG_SAVE_LOCAL = 3; + private static final int MSG_NET_FLOW = 4; private UploadMonitorInfoBean mUploadMonitorBean; private boolean mUploading; private Handler mMainHandler = new Handler(Looper.getMainLooper()); @@ -179,6 +184,10 @@ public class PerformanceDataManager { } else if (msg.what == MSG_MEMORY) { executeMemoryData(); mHandler.sendEmptyMessageDelayed(MSG_MEMORY, NORMAL_FRAME_RATE * 1000); + } else if (msg.what == MSG_NET_FLOW){ + mLastUpBytes = NetworkManager.get().getTotalRequestSize() - mUpBytes; + mLastDownBytes = NetworkManager.get().getTotalResponseSize() - mDownBytes; + mHandler.sendEmptyMessageDelayed(MSG_NET_FLOW, NORMAL_FRAME_RATE * 1000); } else if (msg.what == MSG_SAVE_LOCAL){ saveToLocal(); mHandler.sendEmptyMessageDelayed(MSG_SAVE_LOCAL, NORMAL_FRAME_RATE * 1000); @@ -213,6 +222,14 @@ public class PerformanceDataManager { mHandler.sendEmptyMessageDelayed(MSG_CPU, NORMAL_FRAME_RATE * 1000); } + public void startMonitorNetFlowInfo() { + mHandler.sendEmptyMessageDelayed(MSG_NET_FLOW, NORMAL_FRAME_RATE * 1000); + } + + public void stopMonitorNetFlowInfo() { + mHandler.removeMessages(MSG_NET_FLOW); + } + public void startUploadMonitorData() { mUploading = true; if (mUploadMonitorBean != null) { @@ -229,6 +246,7 @@ public class PerformanceDataManager { } if (PerformanceInfoConfig.isTrafficOpen(mContext)) { NetworkManager.get().startMonitor(); + startMonitorNetFlowInfo(); } mHandler.sendEmptyMessageDelayed(MSG_SAVE_LOCAL, NORMAL_FRAME_RATE * 1000); } @@ -240,6 +258,7 @@ public class PerformanceDataManager { stopMonitorFrameInfo(); stopMonitorCPUInfo(); stopMonitorMemoryInfo(); + stopMonitorNetFlowInfo(); NetworkManager.get().stopMonitor(); } @@ -270,11 +289,25 @@ public class PerformanceDataManager { mUploadMonitorBean.performanceArray = new ArrayList<>(); } } - PerformanceInfo info = new PerformanceInfo(); + NetworkManager networkManager = NetworkManager.get(); + long upSize = networkManager.getTotalRequestSize(); + long downSize = networkManager.getTotalResponseSize(); + + UploadMonitorItem info = new UploadMonitorItem(); info.cpu = mLastCpuRate; info.fps = mLastFrameRate; info.memory = mLastMemoryInfo; + info.upFlow = mLastUpBytes; + info.downFlow = mLastDownBytes; + mUpBytes = upSize; + mDownBytes = downSize; info.timestamp = System.currentTimeMillis(); + + String pageName = "unkown"; + if (DoraemonKit.getCurrentResumedActivity() != null) { + pageName = DoraemonKit.getCurrentResumedActivity().getLocalClassName(); + } + info.page = pageName; mUploadMonitorBean.performanceArray.add(info); } @@ -478,4 +511,12 @@ public class PerformanceDataManager { writeFpsDataIntoFile(); } } + + public long getLastUpBytes() { + return mLastUpBytes; + } + + public long getLastDownBytes() { + return mLastDownBytes; + } } diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/crash/Crash.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/crash/CrashCapture.java similarity index 81% rename from Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/crash/Crash.java rename to Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/crash/CrashCapture.java index f059d3c0045668d36f3b8f87cd4e1fcb7d957297..6b75c99d93dead00cb51314a78da062d21faf527 100644 --- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/crash/Crash.java +++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/crash/CrashCapture.java @@ -11,7 +11,10 @@ import com.didichuxing.doraemonkit.kit.Category; import com.didichuxing.doraemonkit.kit.IKit; import com.didichuxing.doraemonkit.ui.UniversalActivity; -public class Crash implements IKit { +/** + * Created by wanglikun on 2019/6/12 + */ +public class CrashCapture implements IKit { @Override public int getCategory() { return Category.TOOLS; @@ -37,11 +40,11 @@ public class Crash implements IKit { @Override public void onAppInit(Context context) { - + CrashCaptureManager.getInstance().init(context); if (CrashCaptureConfig.isCrashCaptureOpen(context)) { - CrashHandlerManager.getInstance().init(context); + CrashCaptureManager.getInstance().start(); + } else { + CrashCaptureManager.getInstance().stop(); } - } - -} +} \ No newline at end of file diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/crash/CrashCaptureDetailFragment.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/crash/CrashCaptureDetailFragment.java new file mode 100644 index 0000000000000000000000000000000000000000..5d48a92a803e506d85499645605508a17c6ceee6 --- /dev/null +++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/crash/CrashCaptureDetailFragment.java @@ -0,0 +1,59 @@ +package com.didichuxing.doraemonkit.kit.crash; + +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.View; +import android.widget.TextView; + +import com.didichuxing.doraemonkit.R; +import com.didichuxing.doraemonkit.ui.base.BaseFragment; +import com.didichuxing.doraemonkit.ui.crash.CrashHistoryAdapter; +import com.didichuxing.doraemonkit.ui.widget.titlebar.TitleBar; + +import java.util.List; + +public class CrashCaptureDetailFragment extends BaseFragment { + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + initView(); + } + + @Override + protected int onRequestLayout() { + return R.layout.dk_fragment_crash_capture_detail; + } + + private void initView() { + TitleBar mTitleBar = findViewById(R.id.title_bar); + mTitleBar.setOnTitleBarClickListener(new TitleBar.OnTitleBarClickListener() { + @Override + public void onLeftClick() { + finish(); + } + + @Override + public void onRightClick() { + + } + }); + TextView noRecordHint = findViewById(R.id.no_record_hint); + RecyclerView crashList = findViewById(R.id.crash_list); + List caches = CrashCaptureManager.getInstance().getCrashCaches(); + if (caches.isEmpty()) { + noRecordHint.setVisibility(View.VISIBLE); + crashList.setVisibility(View.GONE); + } else { + noRecordHint.setVisibility(View.GONE); + crashList.setVisibility(View.VISIBLE); + crashList.setLayoutManager(new LinearLayoutManager(getContext())); + CrashHistoryAdapter adapter = new CrashHistoryAdapter(getContext()); + adapter.append(caches); + crashList.setAdapter(adapter); + } + } +} diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/crash/CrashCaptureFragment.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/crash/CrashCaptureFragment.java deleted file mode 100644 index 4437b9fc2adbd218be1b4dfc68f065b11e670bc9..0000000000000000000000000000000000000000 --- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/crash/CrashCaptureFragment.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.didichuxing.doraemonkit.kit.crash; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; -import android.widget.AdapterView; -import android.widget.ListView; -import android.widget.Toast; - -import com.didichuxing.doraemonkit.R; -import com.didichuxing.doraemonkit.constant.BundleKey; -import com.didichuxing.doraemonkit.ui.base.BaseFragment; -import com.didichuxing.doraemonkit.ui.crash.CrashCaptureAdapter; -import com.didichuxing.doraemonkit.ui.widget.titlebar.TitleBar; - -import java.io.File; -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; - -public class CrashCaptureFragment extends BaseFragment { - - @Override - public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - initView(); - } - - - @Override - protected int onRequestLayout() { - return R.layout.dk_fragment_crash_capture; - } - - private void initView() { - TitleBar mTitleBar = findViewById(R.id.title_bar); - mTitleBar.setOnTitleBarClickListener(new TitleBar.OnTitleBarClickListener() { - @Override - public void onLeftClick() { - getActivity().onBackPressed(); - } - - @Override - public void onRightClick() { - - } - }); - File file = new File(CrashHandlerManager.getInstance().getFilePath()); - if (file.exists()) { - ListView crash = findViewById(R.id.lv_crash); - final List listFiles = Arrays.asList(file.listFiles()); - if (listFiles != null && listFiles.size() != 0) { - Collections.sort(listFiles, new Comparator() { - @Override - public int compare(File lhs, File rhs) { - return Long.valueOf(rhs.lastModified()) - .compareTo(lhs.lastModified()); - } - }); - crash.setAdapter(new CrashCaptureAdapter(listFiles)); - } else { - Toast.makeText(getContext(), R.string.dk_crash_capture_no_record, Toast.LENGTH_SHORT).show(); - } - crash.setOnItemClickListener(new AdapterView.OnItemClickListener() { - @Override - public void onItemClick(AdapterView parent, View view, int position, long id) { - Bundle bundle = new Bundle(); - File listFile = listFiles.get(position); - bundle.putSerializable(BundleKey.FILE_KEY, listFile); - showContent(CrashDetailFragment.class, bundle); - } - }); - } else { - Toast.makeText(getContext(), R.string.dk_crash_capture_no_record, Toast.LENGTH_SHORT).show(); - } - - } - -} diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/crash/CrashCaptureMainFragment.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/crash/CrashCaptureMainFragment.java index a31bbfc4b1f76b607f433aa28ba539a1a04ee1d9..8eb7e352b512482b13c9cee1b324560ef1ca5dcc 100644 --- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/crash/CrashCaptureMainFragment.java +++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/crash/CrashCaptureMainFragment.java @@ -5,6 +5,7 @@ import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; +import android.text.format.Formatter; import android.view.View; import com.didichuxing.doraemonkit.R; @@ -13,6 +14,7 @@ import com.didichuxing.doraemonkit.ui.base.BaseFragment; import com.didichuxing.doraemonkit.ui.setting.SettingItem; import com.didichuxing.doraemonkit.ui.setting.SettingItemAdapter; import com.didichuxing.doraemonkit.ui.widget.titlebar.HomeTitleBar; +import com.didichuxing.doraemonkit.util.FileUtil; public class CrashCaptureMainFragment extends BaseFragment { @Override @@ -31,27 +33,26 @@ public class CrashCaptureMainFragment extends BaseFragment { titleBar.setListener(new HomeTitleBar.OnTitleBarClickListener() { @Override public void onRightClick() { - getActivity().finish(); + finish(); } }); - - RecyclerView mSettingList = findViewById(R.id.setting_list); - mSettingList.setLayoutManager(new LinearLayoutManager(getContext())); + RecyclerView settingList = findViewById(R.id.setting_list); + settingList.setLayoutManager(new LinearLayoutManager(getContext())); SettingItemAdapter mSettingItemAdapter = new SettingItemAdapter(getContext()); mSettingItemAdapter.append(new SettingItem(R.string.dk_crash_capture_switch, CrashCaptureConfig.isCrashCaptureOpen(getContext()))); mSettingItemAdapter.append(new SettingItem(R.string.dk_crash_capture_look, R.drawable.dk_more_icon)); - mSettingItemAdapter.append(new SettingItem(R.string.dk_crash_capture_clean_data)); - + SettingItem item = new SettingItem(R.string.dk_crash_capture_clean_data); + item.rightDesc = Formatter.formatFileSize(getContext(), FileUtil.getDirectorySize(CrashCaptureManager.getInstance().getCrashCacheDir())); + mSettingItemAdapter.append(item); mSettingItemAdapter.setOnSettingItemSwitchListener(new SettingItemAdapter.OnSettingItemSwitchListener() { @Override public void onSettingItemSwitch(View view, SettingItem data, boolean on) { if (data.desc == R.string.dk_crash_capture_switch) { CrashCaptureConfig.setCrashCaptureOpen(getContext(), on); if (on) { - CrashHandlerManager.getInstance().init(getContext()); + CrashCaptureManager.getInstance().start(); } else { - CrashHandlerManager.getInstance().remove(); - + CrashCaptureManager.getInstance().stop(); } } } @@ -60,13 +61,13 @@ public class CrashCaptureMainFragment extends BaseFragment { @Override public void onSettingItemClick(View view, SettingItem data) { if (data.desc == R.string.dk_crash_capture_look) { - showContent(CrashCaptureFragment.class); + showContent(CrashCaptureDetailFragment.class); } else if (data.desc == R.string.dk_crash_capture_clean_data) { - CrashHandlerManager.getInstance().cleanHistoricalData(); + CrashCaptureManager.getInstance().clearCacheHistory(); + showToast(R.string.dk_crash_capture_clean_data); } } }); - mSettingList.setAdapter(mSettingItemAdapter); - + settingList.setAdapter(mSettingItemAdapter); } } diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/crash/CrashCaptureManager.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/crash/CrashCaptureManager.java new file mode 100644 index 0000000000000000000000000000000000000000..11e1d6299aa3af3e4cf081364e5999cba8229d19 --- /dev/null +++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/crash/CrashCaptureManager.java @@ -0,0 +1,119 @@ +package com.didichuxing.doraemonkit.kit.crash; + +import android.content.Context; +import android.os.Handler; +import android.os.HandlerThread; +import android.util.Log; +import android.widget.Toast; + +import com.didichuxing.doraemonkit.R; +import com.didichuxing.doraemonkit.constant.CachesKey; +import com.didichuxing.doraemonkit.util.CacheUtils; +import com.didichuxing.doraemonkit.util.FileUtil; +import com.didichuxing.doraemonkit.util.LogHelper; + +import java.io.File; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** + * Created by wanglikun on 2019-06-12 + */ +public class CrashCaptureManager implements Thread.UncaughtExceptionHandler { + private static final String TAG = "CrashCaptureManager"; + + private final Thread.UncaughtExceptionHandler mDefaultHandler; + private final Handler mHandler; + private Context mContext; + + private CrashCaptureManager() { + mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler(); + HandlerThread handlerThread = new HandlerThread(TAG); + handlerThread.start(); + mHandler = new Handler(handlerThread.getLooper()); + } + + private static class Holder { + private static final CrashCaptureManager INSTANCE = new CrashCaptureManager(); + } + + public static CrashCaptureManager getInstance() { + return Holder.INSTANCE; + } + + public void init(Context context) { + mContext = context.getApplicationContext(); + } + + public void start() { + Thread.setDefaultUncaughtExceptionHandler(this); + } + + public void stop() { + Thread.setDefaultUncaughtExceptionHandler(mDefaultHandler); + } + + @Override + public void uncaughtException(final Thread t, final Throwable e) { + LogHelper.d(TAG, t.toString()); + LogHelper.d(TAG, Log.getStackTraceString(e)); + CacheUtils.saveObject(e, getCrashCacheFile()); + post(new Runnable() { + @Override + public void run() { + Toast.makeText(mContext, mContext.getString(R.string.dk_crash_capture_tips), Toast.LENGTH_SHORT).show(); + } + }); + postDelay(new Runnable() { + @Override + public void run() { + if (mDefaultHandler != null) { + mDefaultHandler.uncaughtException(t, e); + } + } + }, 2000); + } + + private void post(Runnable r) { + mHandler.post(r); + } + + private void postDelay(Runnable r, long delayMillis) { + mHandler.postDelayed(r, delayMillis); + } + + public File getCrashCacheDir() { + File dir = new File(mContext.getCacheDir() + File.separator + CachesKey.CRASH_HISTORY); + if (!dir.exists()) { + dir.mkdir(); + } + return dir; + } + + private File getCrashCacheFile() { + String fileName = new Date().toString(); + return new File(getCrashCacheDir() + File.separator + fileName); + } + + public void clearCacheHistory() { + FileUtil.deleteDirectory(getCrashCacheDir()); + } + + public List getCrashCaches() { + File[] caches = getCrashCacheDir().listFiles(); + List result = new ArrayList<>(); + if (caches == null) { + return result; + } + for (File cache : caches) { + Serializable serializable = CacheUtils.readObject(cache); + if (serializable instanceof Throwable) { + CrashInfo info = new CrashInfo((Throwable) serializable, cache.lastModified()); + result.add(info); + } + } + return result; + } +} \ No newline at end of file diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/crash/CrashHandlerManager.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/crash/CrashHandlerManager.java deleted file mode 100644 index 24c150de0f26013dfdce43495cd48ce26737e944..0000000000000000000000000000000000000000 --- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/crash/CrashHandlerManager.java +++ /dev/null @@ -1,234 +0,0 @@ -package com.didichuxing.doraemonkit.kit.crash; - -import android.content.Context; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.os.Build; -import android.os.Environment; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.Message; -import android.widget.Toast; - -import com.didichuxing.doraemonkit.R; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.io.Writer; -import java.lang.reflect.Field; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; - - -public class CrashHandlerManager implements Thread.UncaughtExceptionHandler { - - private static final String TAG = CrashHandlerManager.class.getSimpleName(); - - private static class Holder { - private static CrashHandlerManager INSTANCE = new CrashHandlerManager(); - } - - private String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/doraemon/Crash/"; - - private Thread.UncaughtExceptionHandler mDefaultHandler; - - private Map infos = new HashMap(); - - private DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - - private final int CRASH = 10; - - private Handler handler; - - private Context mContext; - - private Boolean isOpen = false; - - public static CrashHandlerManager getInstance() { - return CrashHandlerManager.Holder.INSTANCE; - } - - private CrashHandlerManager() { - - } - - public void init(Context context) { - if (!isOpen) { - isOpen = true; - mContext = context.getApplicationContext(); - mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler(); - Thread.setDefaultUncaughtExceptionHandler(this); - CrashHandlerThread crashHandlerThread = new CrashHandlerThread(TAG); - crashHandlerThread.start(); - handler = new Handler(crashHandlerThread.getLooper(), crashHandlerThread); - } - } - - public void remove() { - if (isOpen) { - isOpen = false; - Thread.setDefaultUncaughtExceptionHandler(mDefaultHandler); - mDefaultHandler = null; - } - - } - - @Override - public void uncaughtException(Thread thread, Throwable ex) { - if (!handleException(ex) && mDefaultHandler != null) { - mDefaultHandler.uncaughtException(thread, ex); - } else { - handler.post(new Runnable() { - @Override - public void run() { - Toast.makeText(mContext, R.string.dk_crash_capture_tips, Toast.LENGTH_LONG).show(); - } - }); - } - - - if (!handleException(ex) && mDefaultHandler != null) { - mDefaultHandler.uncaughtException(thread, ex); - } else { - try { - Thread.sleep(3000); - } catch (InterruptedException e) { - - } - android.os.Process.killProcess(android.os.Process.myPid()); - System.exit(0); - } - } - - - private boolean handleException(Throwable ex) { - if (ex == null) { - return false; - } - handler.sendEmptyMessage(CRASH); - - collectDeviceInfo(); - - saveCrashInfo2File(ex); - return true; - } - - private void collectDeviceInfo() { - try { - PackageManager pm = mContext.getPackageManager(); - PackageInfo pi = pm.getPackageInfo(mContext.getPackageName(), - PackageManager.GET_ACTIVITIES); - if (pi != null) { - String versionName = pi.versionName == null ? "null" - : pi.versionName; - String versionCode = pi.versionCode + ""; - infos.put("versionName", versionName); - infos.put("versionCode", versionCode); - } - } catch (PackageManager.NameNotFoundException e) { - - } - Field[] fields = Build.class.getDeclaredFields(); - for (Field field : fields) { - try { - field.setAccessible(true); - infos.put(field.getName(), field.get(null).toString()); - } catch (Exception e) { - } - } - } - - public String getFilePath() { - return path; - } - - private String saveCrashInfo2File(Throwable ex) { - - StringBuffer sb = new StringBuffer(); - for (Map.Entry entry : infos.entrySet()) { - String key = entry.getKey(); - String value = entry.getValue(); - sb.append(key + "=" + value + "\n"); - } - sb.append("\n"); - Writer writer = new StringWriter(); - PrintWriter printWriter = new PrintWriter(writer); - ex.printStackTrace(printWriter); - Throwable cause = ex.getCause(); - while (cause != null) { - cause.printStackTrace(printWriter); - cause = cause.getCause(); - } - printWriter.close(); - String result = writer.toString(); - sb.append(result); - try { - String fileName = formatter.format(new Date()) + ".txt"; - if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { - File dir = new File(path); - if (!dir.exists()) { - dir.mkdirs(); - } - FileOutputStream fos = new FileOutputStream(path + fileName); - fos.write(sb.toString().getBytes()); - fos.close(); - } - return fileName; - } catch (Exception e) { - - } - return null; - } - - public void cleanHistoricalData() { - try { - File file = new File(getFilePath()); - if (file.exists()) { - RecursionDeleteFile(file); - } - } catch (Exception e) { - - } - - } - - public void RecursionDeleteFile(File file) { - if (file.isFile()) { - file.delete(); - return; - } - if (file.isDirectory()) { - File[] childFile = file.listFiles(); - if (childFile == null || childFile.length == 0) { - file.delete(); - return; - } - for (File f : childFile) { - RecursionDeleteFile(f); - } - file.delete(); - } - } - - private class CrashHandlerThread extends HandlerThread implements android.os.Handler.Callback { - - public CrashHandlerThread(String name) { - super(name); - } - - - @Override - public boolean handleMessage(Message msg) { - if (msg.what == CRASH) { - Toast.makeText(mContext, R.string.dk_crash_capture_tips, Toast.LENGTH_LONG).show(); - } - return true; - } - } - -} \ No newline at end of file diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/crash/CrashInfo.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/crash/CrashInfo.java new file mode 100644 index 0000000000000000000000000000000000000000..4952f80fff0b942b18bb9215cd50359e6368a29e --- /dev/null +++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/crash/CrashInfo.java @@ -0,0 +1,17 @@ +package com.didichuxing.doraemonkit.kit.crash; + +import java.io.Serializable; + +/** + * Created by wanglikun on 2019-06-12 + */ +public class CrashInfo implements Serializable { + public final Throwable tr; + + public final long time; + + public CrashInfo(Throwable tr, long l) { + this.tr = tr; + this.time = l; + } +} \ No newline at end of file diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/custom/PageDataFragment.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/custom/PageDataFragment.java index bafeb2325abf02f90cc0288cbd93d9f308d36fef..27fdcf364a4d6cfd2583ffecd22e642d05461b95 100644 --- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/custom/PageDataFragment.java +++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/custom/PageDataFragment.java @@ -11,20 +11,22 @@ import android.view.View; import com.didichuxing.doraemonkit.R; import com.didichuxing.doraemonkit.kit.common.PerformanceDataManager; import com.didichuxing.doraemonkit.ui.base.BaseFragment; -import com.didichuxing.doraemonkit.ui.fileexplorer.FileInfo; import com.didichuxing.doraemonkit.ui.widget.recyclerview.DividerItemDecoration; -import com.didichuxing.doraemonkit.ui.widget.titlebar.HomeTitleBar; import com.didichuxing.doraemonkit.ui.widget.titlebar.TitleBar; import com.didichuxing.doraemonkit.util.JsonUtil; -import com.google.gson.reflect.TypeToken; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; -import java.lang.reflect.Type; +import java.text.DecimalFormat; import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; public class PageDataFragment extends BaseFragment { private RecyclerView mRvList; @@ -99,53 +101,75 @@ public class PageDataFragment extends BaseFragment { return dataItems; } + Map> listMap = new TreeMap<>(); for (UploadMonitorInfoBean infoBean : infoBeans) { if(null == infoBean || null == infoBean.performanceArray || 0 >= infoBean.performanceArray.size()){ continue; } - PageDataItem item = new PageDataItem(); - - List performanceInfos = infoBean.performanceArray; - item.pageName = infoBean.appName; - - item.upNetWork =new PageDataItemChild<>(R.string.dk_frameinfo_upstream); - item.downNetWork = new PageDataItemChild<>(R.string.dk_frameinfo_downstream); - item.memory = new PageDataItemChild<>(R.string.dk_frameinfo_ram); - item.cpu = new PageDataItemChild<>(R.string.dk_frameinfo_cpu); - item.fps = new PageDataItemChild<>(R.string.dk_frameinfo_fps); + List performanceInfos = infoBean.performanceArray; + for (UploadMonitorItem item : performanceInfos) { + List itemList = listMap.get(item.page); + if(null == itemList){ + itemList = new ArrayList<>(); + listMap.put(item.page, itemList); + } - for (PerformanceInfo info : performanceInfos) { - setValue(item.memory,info.memory); - setValue(item.cpu,info.cpu); - setValue(item.fps,info.fps); + itemList.add(item); } + } - item.memory.avg /= performanceInfos.size(); - item.cpu.avg /= performanceInfos.size(); - item.fps.avg /= performanceInfos.size(); - - dataItems.add(item); + for (String pageName : listMap.keySet()) { + dataItems.addAll(getPageItemData(pageName, listMap.get(pageName))); } return dataItems; } - private void setValue(PageDataItemChild child, float newValue) { - child.min = Math.min(null == child.min ? 0:child.min, newValue); - child.max = Math.max(null == child.max ? 0:child.max, newValue); - child.avg = (null == child.avg ? 0:child.avg)+newValue; - } - private void setValue(PageDataItemChild child, int newValue) { - child.min = Math.min(null == child.min ? 0:child.min, newValue); - child.max = Math.max(null == child.max ? 0:child.max, newValue); - child.avg = (null == child.avg ? 0:child.avg)+newValue; + private List getPageItemData(String appName, List performanceInfos) { + List dataItems = new ArrayList<>(); + + PageDataItem item = new PageDataItem(); + item.pageName = appName; + + item.upNetWork =new PageDataItemChild(R.string.dk_frameinfo_upstream); + item.downNetWork = new PageDataItemChild(R.string.dk_frameinfo_downstream); + item.memory = new PageDataItemChild(R.string.dk_frameinfo_ram); + item.cpu = new PageDataItemChild(R.string.dk_frameinfo_cpu); + item.fps = new PageDataItemChild(R.string.dk_frameinfo_fps); + + for (UploadMonitorItem monitorItem : performanceInfos) { + setValue(item.upNetWork,monitorItem.upFlow); + setValue(item.downNetWork,monitorItem.downFlow); + setValue(item.memory,monitorItem.memory); + setValue(item.cpu,monitorItem.cpu); + setValue(item.fps,monitorItem.fps); + } + + int size = performanceInfos.size(); + if(0 < size){ + item.upNetWork.avg /= size; + item.downNetWork.avg /= size; + item.memory.avg /= size; + item.cpu.avg /= size; + item.fps.avg /= size; + }else{ + item.upNetWork.avg = 0; + item.downNetWork.avg = 0; + item.memory.avg = 0; + item.cpu.avg = 0; + item.fps.avg = 0; + } + + dataItems.add(item); + + return dataItems; } - private void setValue(PageDataItemChild child, double newValue) { - child.min = Math.min(null == child.min ? 0:child.min, newValue); - child.max = Math.max(null == child.max ? 0:child.max, newValue); - child.avg = (null == child.avg ? 0:child.avg)+newValue; + private void setValue(PageDataItemChild child, double newValue) { + child.min = 0 == child.min || 0 == newValue ? child.min+newValue : Math.min(child.min, newValue); + child.max = 0 == child.max || 0 == newValue ? child.max+newValue : Math.max(child.max, newValue); + child.avg += newValue; } private String getFileString(File file) { diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/custom/PageDataItem.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/custom/PageDataItem.java index b1435793a2e411626efb8d77c3e2428c8ba7d8b1..69ac8f326800bf2488d1dc4dbf3d41f8273d8da9 100644 --- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/custom/PageDataItem.java +++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/custom/PageDataItem.java @@ -6,27 +6,27 @@ import android.view.View; public class PageDataItem { public String pageName; - public PageDataItemChild upNetWork; - public PageDataItemChild downNetWork; - public PageDataItemChild memory; - public PageDataItemChild cpu; - public PageDataItemChild fps; + public PageDataItemChild upNetWork; + public PageDataItemChild downNetWork; + public PageDataItemChild memory; + public PageDataItemChild cpu; + public PageDataItemChild fps; public PageDataItem() { } } -class PageDataItemChild { +class PageDataItemChild { @StringRes public int nameResId; - public T min; - public T max; - public T avg; + public double min; + public double max; + public double avg; public PageDataItemChild(int nameResId) { this.nameResId = nameResId; } - public int getVisibility(PageDataItemChild child){ + public int getVisibility(PageDataItemChild child){ return 0 < getValue(child.min)+ getValue(child.max) + getValue(child.avg) ? View.VISIBLE: View.GONE; } @@ -43,23 +43,27 @@ class PageDataItemChild { this.nameResId = nameResId; } - public void setMin(T min) { + public double getMin() { + return min; + } + + public void setMin(double min) { this.min = min; } - public T getMax() { + public double getMax() { return max; } - public void setMax(T max) { + public void setMax(double max) { this.max = max; } - public T getAvg() { + public double getAvg() { return avg; } - public void setAvg(T avg) { + public void setAvg(double avg) { this.avg = avg; } } diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/custom/PageDataItemAdapter.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/custom/PageDataItemAdapter.java index 958d8059bb47efd172170f5f3e3dd3276142e13a..8cde7d8b51eacb3f7d285c0ea5799c31c094ca3c 100644 --- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/custom/PageDataItemAdapter.java +++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/custom/PageDataItemAdapter.java @@ -10,6 +10,8 @@ import com.didichuxing.doraemonkit.R; import com.didichuxing.doraemonkit.ui.widget.recyclerview.AbsRecyclerAdapter; import com.didichuxing.doraemonkit.ui.widget.recyclerview.AbsViewBinder; +import java.text.DecimalFormat; + public class PageDataItemAdapter extends AbsRecyclerAdapter, PageDataItem> { private Context mContext; public PageDataItemAdapter(Context context) { @@ -63,7 +65,7 @@ public class PageDataItemAdapter extends AbsRecyclerAdapter data) { + private void setValue(View iteView, PageDataItemChild data) { int visibility = data.getVisibility(data); iteView.setVisibility(visibility); if(View.GONE == visibility){ @@ -72,23 +74,28 @@ public class PageDataItemAdapter extends AbsRecyclerAdapter records = NetworkManager.get().getRecords(); - long requestLength = null != records && 0 < records.size() ? records.get(records.size() - 1).requestLength : 0; - long responseLength = null != records && 0 < records.size() ? records.get(records.size() - 1).responseLength : 0; - mDownNetworkTxt.setText(String.format("%s: %sB", getString(R.string.dk_frameinfo_downstream), requestLength)); - mUpNetworkTxt.setText(String.format("%s: %sB", getString(R.string.dk_frameinfo_upstream), responseLength)); + mDownNetworkTxt.setText(String.format("%s%s", getString(R.string.dk_frameinfo_downstream), getFlowTxt(manager.getLastDownBytes()))); + mUpNetworkTxt.setText(String.format("%s%s", getString(R.string.dk_frameinfo_upstream), getFlowTxt(manager.getLastUpBytes()))); }else{ mDownNetworkTxt.setVisibility(View.INVISIBLE); mUpNetworkTxt.setVisibility(View.INVISIBLE); } } + public static String getFlowTxt(long flowBytes) { + String upFlowTxt = flowBytes+"B"; + if(1073741824 < flowBytes) { + upFlowTxt = flowBytes/1073741824 +"GB"; + }else if(1048576 < flowBytes) { + upFlowTxt = flowBytes/1048576 +"MB"; + }else if(1024 < flowBytes) { + upFlowTxt = flowBytes/1024 +"KB"; + } + + return upFlowTxt; + } + @Override public void onMove(int x, int y, int dx, int dy) { getLayoutParams().x += dx; diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/custom/UploadMonitorInfoBean.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/custom/UploadMonitorInfoBean.java index 21f9acb7ba939592d1b1937f256e638fa909e38c..ac545d6f96628477b833885293707c8df710567e 100644 --- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/custom/UploadMonitorInfoBean.java +++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/custom/UploadMonitorInfoBean.java @@ -5,6 +5,6 @@ import java.util.List; public class UploadMonitorInfoBean { public long timestamp; public String appName; - public List performanceArray; + public List performanceArray; } diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/custom/UploadMonitorItem.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/custom/UploadMonitorItem.java new file mode 100644 index 0000000000000000000000000000000000000000..73a853b12a1d9c83c426fd65f9d0ddb8c4de11b5 --- /dev/null +++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/custom/UploadMonitorItem.java @@ -0,0 +1,11 @@ +package com.didichuxing.doraemonkit.kit.custom; + +public class UploadMonitorItem { + public String page = "unkown"; + public long timestamp; + public int fps; + public float memory; + public float cpu; + public long upFlow; + public long downFlow; +} diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/fileexplorer/SpAdapter.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/fileexplorer/SpAdapter.java index 3890647a1d2fcbee26ce0eaa793a854c2707ac4d..ba4470c1f9fedf08003625986b9b140f327f03a6 100644 --- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/fileexplorer/SpAdapter.java +++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/fileexplorer/SpAdapter.java @@ -50,14 +50,13 @@ public class SpAdapter extends AbsRecyclerAdapter, SpBean> if (spBean.value.getClass().getSimpleName() != SpInputType.HASHSET) { key.setText(spBean.key); type.setText(spBean.value.getClass().getSimpleName()); - inputView.setInput(spBean.value, new SpInputView.OnDataChangeListener() { + inputView.setInput(spBean, new SpInputView.OnDataChangeListener() { @Override - public void onDataChanged(Object o) { - spBean.value = o; + public void onDataChanged() { + inputView.refresh(); if (onSpDataChangerListener != null) { - onSpDataChangerListener.onDataChanged(spBean.key, spBean.value); + onSpDataChangerListener.onDataChanged(spBean); } - } }); } @@ -70,8 +69,8 @@ public class SpAdapter extends AbsRecyclerAdapter, SpBean> this.onSpDataChangerListener = onSpDataChangerListener; } - public interface OnSpDataChangerListener { - void onDataChanged(String key, T t); + public interface OnSpDataChangerListener { + void onDataChanged(SpBean spBean); } } diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/fileexplorer/SpBean.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/fileexplorer/SpBean.java index 5719c7e8b1633d7c2b98a4b31676a725a0fc58c1..e1422ebeabd50698c22993f5a187ed0b4b8a1fb3 100644 --- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/fileexplorer/SpBean.java +++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/fileexplorer/SpBean.java @@ -1,6 +1,43 @@ package com.didichuxing.doraemonkit.kit.fileexplorer; -class SpBean { +import com.didichuxing.doraemonkit.constant.SpInputType; + +public class SpBean { public String key; - public T value; + public Object value; + public Class clazz; + + private SpBean() { + + } + + public SpBean(String key, Object value) { + this.key = key; + this.value = value; + clazz = value.getClass(); + } + + public Object toDefaultClass(String string) { + setDefaultClass(string); + return value; + } + + private void setDefaultClass(String string) { + switch (clazz.getSimpleName()) { + case SpInputType.FLOAT: + value = Float.valueOf(string); + break; + case SpInputType.INTEGER: + value = Integer.valueOf(string); + break; + case SpInputType.STRING: + value = String.valueOf(string); + break; + case SpInputType.LONG: + value = Long.valueOf(string); + break; + } + + } + } diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/fileexplorer/SpFragment.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/fileexplorer/SpFragment.java index 0f8ee30cb340131c3b1f798586484989eebbc42b..a5baf77eabdd0e7026f0539cf59a3eab9b271894 100644 --- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/fileexplorer/SpFragment.java +++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/fileexplorer/SpFragment.java @@ -1,6 +1,5 @@ package com.didichuxing.doraemonkit.kit.fileexplorer; -import android.content.Context; import android.content.SharedPreferences; import android.os.Bundle; import android.support.annotation.NonNull; @@ -15,77 +14,73 @@ import com.didichuxing.doraemonkit.constant.BundleKey; import com.didichuxing.doraemonkit.constant.SpInputType; import com.didichuxing.doraemonkit.ui.base.BaseFragment; import com.didichuxing.doraemonkit.ui.widget.titlebar.TitleBar; +import com.didichuxing.doraemonkit.util.SharedPrefsUtil; import java.io.File; import java.util.ArrayList; -import java.util.HashSet; +import java.util.List; import java.util.Map; import static com.didichuxing.doraemonkit.util.FileUtil.XML; public class SpFragment extends BaseFragment { - private ArrayList spBeans; private SharedPreferences.Editor edit; - private String spNameFileName; + private String spTableName; - private View.OnClickListener mOnClickListener = new View.OnClickListener() { - @Override - public void onClick(View v) { - int id = v.getId(); - if (id == R.id.btn_submit) { - boolean commit = edit.commit(); - if (commit) { - finish(); - showToast(R.string.dk_success); - } else { - showToast(R.string.dk_fail); - } - } else if (id == R.id.btn_cancel) { - finish(); - } - - } - }; - @Override protected int onRequestLayout() { return R.layout.dk_fragment_sp_show; } - @Override - public void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - Bundle data = getArguments(); - if (data != null) { - File mFile = (File) data.getSerializable(BundleKey.FILE_KEY); - spNameFileName = mFile.getName().replace(XML, ""); - SharedPreferences sharedPreferences = getActivity().getSharedPreferences(spNameFileName, Context.MODE_PRIVATE); - edit = sharedPreferences.edit(); - - Map all = sharedPreferences.getAll(); - spBeans = new ArrayList<>(all.size()); - SpBean spBean; - for (Map.Entry entry : all.entrySet()) { - Object value = entry.getValue(); - spBean = new SpBean(); - spBean.key = entry.getKey(); - spBean.value = value; - spBeans.add(spBean); - } + private List getSpBeans() { + ArrayList spBeans = new ArrayList<>(); + + File mFile = (File) getArguments().getSerializable(BundleKey.FILE_KEY); + if (mFile == null) { + return spBeans; + } + spTableName = mFile.getName().replace(XML, ""); + SharedPreferences sp = SharedPrefsUtil.getSharedPrefs(getActivity(), spTableName); + edit = sp.edit(); + Map all = sp.getAll(); + if (all.isEmpty()) { + return spBeans; } + for (Map.Entry entry : all.entrySet()) { + spBeans.add(new SpBean(entry.getKey(), entry.getValue())); + } + return spBeans; + } @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); - if (spBeans != null && spBeans.size() > 0) { + List spBeans = getSpBeans(); + if (spBeans.isEmpty()) { + finish(); + return; + } + RecyclerView recyclerView = findViewById(R.id.rv_sp); + recyclerView.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false)); + recyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL)); + SpAdapter spAdapter = new SpAdapter(getActivity()); + spAdapter.setOnSpDataChangerListener(new SpAdapter.OnSpDataChangerListener() { + @Override + public void onDataChanged(SpBean bean) { + spUpData(bean); + } + }); + spAdapter.append(spBeans); + recyclerView.setAdapter(spAdapter); + if (spTableName != null) { TitleBar mTitleBar = findViewById(R.id.title_bar); - mTitleBar.setTitle(spNameFileName); + mTitleBar.setTitle(spTableName); mTitleBar.setOnTitleBarClickListener(new TitleBar.OnTitleBarClickListener() { @Override public void onLeftClick() { - onBackPressed(); + finish(); } @Override @@ -93,47 +88,31 @@ public class SpFragment extends BaseFragment { } }); - RecyclerView recyclerView = findViewById(R.id.rv_sp); - recyclerView.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false)); - recyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL)); - SpAdapter spAdapter = new SpAdapter(getActivity()); - spAdapter.append(spBeans); - spAdapter.setOnSpDataChangerListener(new SpAdapter.OnSpDataChangerListener() { - @Override - public void onDataChanged(String key, Object o) { - spUpData(key, o); - } - }); - recyclerView.setAdapter(spAdapter); - - findViewById(R.id.btn_submit).setOnClickListener(mOnClickListener); - findViewById(R.id.btn_cancel).setOnClickListener(mOnClickListener); - } else { - finish(); } + } - public void spUpData(String key, Object o) { - String simpleName = o.getClass().getSimpleName(); - if (simpleName.equals(SpInputType.STRING)) { - edit.putString(key, o.toString()); - } - if (simpleName.equals(SpInputType.BOOLEAN)) { - edit.putBoolean(key, (Boolean) o); - } - if (simpleName.equals(SpInputType.HASHSET)) { - edit.putStringSet(key, (HashSet) o); - } - if (simpleName.equals(SpInputType.INTEGER)) { - edit.putInt(key, (Integer) o); - } - if (simpleName.equals(SpInputType.FLOAT)) { - edit.putFloat(key, (Float) o); - } - if (simpleName.equals(SpInputType.LONG)) { - edit.putLong(key, (Long) o); + + public void spUpData(SpBean bean) { + String key = bean.key; + switch (bean.value.getClass().getSimpleName()) { + case SpInputType.STRING: + SharedPrefsUtil.putString(getActivity(), key, bean.value.toString()); + break; + case SpInputType.BOOLEAN: + SharedPrefsUtil.putBoolean(getActivity(), spTableName, key, (Boolean) bean.value); + break; + case SpInputType.INTEGER: + SharedPrefsUtil.putInt(getActivity(), spTableName, key, (Integer) bean.value); + break; + case SpInputType.FLOAT: + SharedPrefsUtil.putFloat(getActivity(), spTableName, key, (Float) bean.value); + break; + case SpInputType.LONG: + SharedPrefsUtil.putLong(getActivity(), spTableName, key, (Long) bean.value); + break; } - } + } } diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/fileexplorer/SpInputView.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/fileexplorer/SpInputView.java index dec4e6685d771c0666097685b2e8d25c012cb5a8..5371ab2f3459b0ab0d33c81918f0758cec35f482 100644 --- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/fileexplorer/SpInputView.java +++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/fileexplorer/SpInputView.java @@ -2,36 +2,35 @@ package com.didichuxing.doraemonkit.kit.fileexplorer; import android.content.Context; import android.support.annotation.Nullable; -import android.text.Editable; import android.text.InputType; -import android.text.TextWatcher; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; -import android.widget.AdapterView; -import android.widget.ArrayAdapter; -import android.widget.EditText; +import android.widget.CompoundButton; import android.widget.FrameLayout; -import android.widget.Spinner; +import android.widget.Switch; +import android.widget.TextView; import com.didichuxing.doraemonkit.R; import com.didichuxing.doraemonkit.constant.SpInputType; - -import java.util.ArrayList; -import java.util.List; +import com.didichuxing.doraemonkit.ui.widget.bottomview.BottomUpWindow; +import com.didichuxing.doraemonkit.ui.widget.bottomview.EditSpInputView; public class SpInputView extends FrameLayout { - private Spinner spinner; - private EditText sp_input; - private static final List selected = new ArrayList() {{ - add(true); - add(false); - }}; + private OnDataChangeListener onDataChangeListener; + + private static final int FLOAT = InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL; + private static final int INTEGER = InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_SIGNED; + private static final int STRING = InputType.TYPE_CLASS_TEXT; + + private TextView spValue; + private Switch switchBtn; + private SpBean bean; + public SpInputView(Context context) { - super(context); - init(); + super(context, null); } public SpInputView(Context context, @Nullable AttributeSet attrs) { @@ -48,43 +47,36 @@ public class SpInputView extends FrameLayout { private void init() { View inflate = LayoutInflater.from(getContext()).inflate(R.layout.kd_item_sp_input, this, true); - spinner = inflate.findViewById(R.id.spinner); - spinner.setAdapter(new ArrayAdapter<>(getContext(), android.R.layout.simple_list_item_1, selected)); - sp_input = inflate.findViewById(R.id.sp_input); + switchBtn = inflate.findViewById(R.id.switch_btn); + spValue = inflate.findViewById(R.id.tv_sp_value); } - private String currentStatue = ""; - - public void setInput(final T t, final OnDataChangeListener onDataChangeListener) { - currentStatue = t.getClass().getSimpleName(); - switch (currentStatue) { + public void setInput(final SpBean bean, final OnDataChangeListener onDataChangeListener) { + this.bean = bean; + this.onDataChangeListener = onDataChangeListener; + switch (bean.value.getClass().getSimpleName()) { case SpInputType.BOOLEAN: - spinner.setSelection(selected.indexOf(t)); - spinner.setVisibility(VISIBLE); - spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + switchBtn.setChecked((Boolean) bean.value); + switchBtn.setVisibility(VISIBLE); + switchBtn.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override - public void onItemSelected(AdapterView parent, View view, int position, long id) { - onDataChangeListener.onDataChanged(parent.getSelectedItem()); - } - - @Override - public void onNothingSelected(AdapterView parent) { - + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + bean.value = isChecked; + onDataChangeListener.onDataChanged(); } }); - sp_input.setVisibility(GONE); + spValue.setVisibility(GONE); break; case SpInputType.INTEGER: case SpInputType.LONG: + initEdt(bean, INTEGER); + break; case SpInputType.FLOAT: - sp_input.setInputType(InputType.TYPE_CLASS_NUMBER); - initEdt(t, onDataChangeListener); + initEdt(bean, FLOAT); break; case SpInputType.STRING: - sp_input.setInputType(InputType.TYPE_CLASS_TEXT); - initEdt(t, onDataChangeListener); - + initEdt(bean, STRING); break; default: break; @@ -94,32 +86,44 @@ public class SpInputView extends FrameLayout { } } - private void initEdt(T t, final OnDataChangeListener onDataChangeListener) { - sp_input.setText(t.toString()); - sp_input.setVisibility(VISIBLE); - spinner.setVisibility(GONE); - sp_input.addTextChangedListener(new TextWatcher() { + private void initEdt(final SpBean spBean, final int inputType) { + spValue.setVisibility(VISIBLE); + switchBtn.setVisibility(GONE); + spValue.setText(spBean.value.toString()); + spValue.setOnClickListener(new OnClickListener() { @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - + public void onClick(View v) { + showInputView(v, spBean, inputType); } + }); + } - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { + public void refresh() { + if (bean != null) { + spValue.setText(bean.value.toString()); + } + } + private void showInputView(View view, final SpBean spBean, int inputType) { + new BottomUpWindow(getContext()).setContent(new EditSpInputView(getContext(), spBean, inputType)) + .show(view).setOnSubmitListener(new BottomUpWindow.OnSubmitListener() { + @Override + public void submit(Object object) { + spBean.value = object; + if (onDataChangeListener != null) { + onDataChangeListener.onDataChanged(); + } } @Override - public void afterTextChanged(Editable s) { - - onDataChangeListener.onDataChanged(s.toString()); + public void cancel() { } }); } - public interface OnDataChangeListener { - void onDataChanged(T t); + public interface OnDataChangeListener { + void onDataChanged(); } } diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/bean/NetflowInfo.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/bean/NetflowInfo.java new file mode 100644 index 0000000000000000000000000000000000000000..be8c2354170596d61b7daabf5ae9a33513cdbae3 --- /dev/null +++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/network/bean/NetflowInfo.java @@ -0,0 +1,8 @@ +package com.didichuxing.doraemonkit.kit.network.bean; + +public class NetflowInfo { + public long flow; + public long timestamp; + public String page; + public boolean isUp; +} diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/parameter/frameInfo/FrameInfoFragment.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/parameter/frameInfo/FrameInfoFragment.java index eff05c70b8514bc29d908fafc5cc3447c4440119..f510ac433d1b9058a142f0d75bc0ce45dc261498 100644 --- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/parameter/frameInfo/FrameInfoFragment.java +++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/parameter/frameInfo/FrameInfoFragment.java @@ -1,18 +1,17 @@ package com.didichuxing.doraemonkit.kit.parameter.frameInfo; import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.view.View; - import com.didichuxing.doraemonkit.R; -import com.didichuxing.doraemonkit.config.PerformanceInfoConfig; import com.didichuxing.doraemonkit.constant.BundleKey; -import com.didichuxing.doraemonkit.kit.parameter.AbsParameterFragment; import com.didichuxing.doraemonkit.kit.common.PerformanceDataManager; import com.didichuxing.doraemonkit.kit.common.PerformanceFragment; +import com.didichuxing.doraemonkit.kit.parameter.AbsParameterFragment; import com.didichuxing.doraemonkit.ui.realtime.datasource.DataSourceFactory; import com.didichuxing.doraemonkit.ui.setting.SettingItem; import com.didichuxing.doraemonkit.ui.setting.SettingItemAdapter; - import java.util.Collection; import java.util.List; @@ -22,6 +21,12 @@ import java.util.List; public class FrameInfoFragment extends AbsParameterFragment { + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + PerformanceDataManager.getInstance().init(getContext().getApplicationContext()); + } + @Override protected int getTitle() { return R.string.dk_kit_frame_info_desc; @@ -75,4 +80,4 @@ public class FrameInfoFragment extends AbsParameterFragment { closeChartPage(); } -} \ No newline at end of file +} diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/PrinterParser.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/PrinterParser.java deleted file mode 100644 index 7cdaa9d71fdb59d26a81d99b953968a672b465de..0000000000000000000000000000000000000000 --- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/PrinterParser.java +++ /dev/null @@ -1,112 +0,0 @@ -package com.didichuxing.doraemonkit.kit.timecounter; - -import android.text.TextUtils; -import android.util.Printer; - -import com.didichuxing.doraemonkit.util.LogHelper; - -/** - * @author: linjizong - * @date: 2019/2/19 - * @desc: - */ -public class PrinterParser implements Printer { - private static final String DISPATCHING_TAG = ">>>>> Dispatching"; - private static final String FINISHED_TAG = "<<<<< Finished"; - private static final String HANDLER_NAME = "android.app.ActivityThread$H"; - - public static final int LAUNCH_ACTIVITY = 100; - public static final int PAUSE_ACTIVITY = 101; - public static final int PAUSE_ACTIVITY_FINISHING = 102; - public static final int STOP_ACTIVITY_SHOW = 103; - public static final int STOP_ACTIVITY_HIDE = 104; - public static final int SHOW_WINDOW = 105; - public static final int HIDE_WINDOW = 106; - public static final int RESUME_ACTIVITY = 107; - public static final int SEND_RESULT = 108; - public static final int DESTROY_ACTIVITY = 109; - public static final int BIND_APPLICATION = 110; - public static final int EXIT_APPLICATION = 111; - public static final int NEW_INTENT = 112; - public static final int RECEIVER = 113; - public static final int CREATE_SERVICE = 114; - public static final int SERVICE_ARGS = 115; - public static final int STOP_SERVICE = 116; - - public static final int CONFIGURATION_CHANGED = 118; - public static final int CLEAN_UP_CONTEXT = 119; - public static final int GC_WHEN_IDLE = 120; - public static final int BIND_SERVICE = 121; - public static final int UNBIND_SERVICE = 122; - public static final int DUMP_SERVICE = 123; - public static final int LOW_MEMORY = 124; - public static final int ACTIVITY_CONFIGURATION_CHANGED = 125; - public static final int RELAUNCH_ACTIVITY = 126; - public static final int PROFILER_CONTROL = 127; - public static final int CREATE_BACKUP_AGENT = 128; - public static final int DESTROY_BACKUP_AGENT = 129; - public static final int SUICIDE = 130; - public static final int REMOVE_PROVIDER = 131; - public static final int ENABLE_JIT = 132; - public static final int DISPATCH_PACKAGE_BROADCAST = 133; - public static final int SCHEDULE_CRASH = 134; - public static final int DUMP_HEAP = 135; - public static final int DUMP_ACTIVITY = 136; - public static final int SLEEPING = 137; - public static final int SET_CORE_SETTINGS = 138; - public static final int UPDATE_PACKAGE_COMPATIBILITY_INFO = 139; - public static final int TRIM_MEMORY = 140; - public static final int DUMP_PROVIDER = 141; - public static final int UNSTABLE_PROVIDER_DIED = 142; - public static final int REQUEST_ASSIST_CONTEXT_EXTRAS = 143; - public static final int TRANSLUCENT_CONVERSION_COMPLETE = 144; - public static final int INSTALL_PROVIDER = 145; - public static final int ON_NEW_ACTIVITY_OPTIONS = 146; - public static final int CANCEL_VISIBLE_BEHIND = 147; - public static final int BACKGROUND_VISIBLE_BEHIND_CHANGED = 148; - public static final int ENTER_ANIMATION_COMPLETE = 149; - public static final int START_BINDER_TRACKING = 150; - public static final int STOP_BINDER_TRACKING_AND_DUMP = 151; - public static final int MULTI_WINDOW_MODE_CHANGED = 152; - public static final int PICTURE_IN_PICTURE_MODE_CHANGED = 153; - public static final int LOCAL_VOICE_INTERACTION_STARTED = 154; - public static final int ATTACH_AGENT = 155; - public static final int APPLICATION_INFO_CHANGED = 156; - public static final int ACTIVITY_MOVED_TO_DISPLAY = 157; - - private int sCurrentMsg; - - public void parse(String log) { - if (TextUtils.isEmpty(log)) { - return; - } - if (!log.contains(HANDLER_NAME)) { - return; - } - if (log.startsWith(DISPATCHING_TAG)) { - if (log.endsWith(String.valueOf(PAUSE_ACTIVITY))) { - LogHelper.d("PinterParser", "pause"); - TimeCounterManager.get().onActivityStart(); - sCurrentMsg = PAUSE_ACTIVITY; - } else if (log.endsWith(String.valueOf(LAUNCH_ACTIVITY))) { - LogHelper.d("PinterParser", "launch"); - TimeCounterManager.get().onActivityLaunch(); - sCurrentMsg = LAUNCH_ACTIVITY; - } - } else if (log.startsWith(FINISHED_TAG)) { - if (sCurrentMsg == PAUSE_ACTIVITY) { - LogHelper.d("PinterParser", "pause end"); - TimeCounterManager.get().onActivityPaused(); - } else if (sCurrentMsg == LAUNCH_ACTIVITY) { - LogHelper.d("PinterParser", "launch end"); - TimeCounterManager.get().onActivityCreated(); - } - sCurrentMsg = 0; - } - } - - @Override - public void println(String x) { - parse(x); - } -} diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/TimeCounterManager.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/TimeCounterManager.java index a9b3c204d1593333f568de52cdafa557ef38cdbe..27867a72b6096be2bf51257d7f13796eede8e416 100644 --- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/TimeCounterManager.java +++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/TimeCounterManager.java @@ -3,7 +3,6 @@ package com.didichuxing.doraemonkit.kit.timecounter; import android.os.Looper; import com.didichuxing.doraemonkit.constant.PageTag; -import com.didichuxing.doraemonkit.kit.blockmonitor.core.BlockMonitorManager; import com.didichuxing.doraemonkit.kit.timecounter.bean.CounterInfo; import com.didichuxing.doraemonkit.kit.timecounter.counter.ActivityCounter; import com.didichuxing.doraemonkit.kit.timecounter.counter.AppCounter; @@ -22,8 +21,6 @@ public class TimeCounterManager { private static TimeCounterManager INSTANCE = new TimeCounterManager(); } - private PrinterParser mParser = new PrinterParser(); - public static TimeCounterManager get() { return TimeCounterManager.Holder.INSTANCE; } @@ -39,12 +36,8 @@ public class TimeCounterManager { mAppCounter.end(); } - public long getAppInitTime() { - return mAppCounter.getTime(); - } - - public void onActivityStart() { - mActivityCounter.start(); + public void onActivityPause() { + mActivityCounter.pause(); } public void onActivityPaused() { @@ -55,7 +48,7 @@ public class TimeCounterManager { mActivityCounter.launch(); } - public void onActivityCreated() { + public void onActivityLaunched() { mActivityCounter.launchEnd(); } @@ -68,9 +61,6 @@ public class TimeCounterManager { return; } mIsRunning = true; - // 卡顿检测和跳转耗时统计都使用了Printer的方式,无法同时工作 - BlockMonitorManager.getInstance().stop(); - Looper.getMainLooper().setMessageLogging(mParser); PageIntent pageIntent = new PageIntent(TimeCounterFloatPage.class); pageIntent.tag = PageTag.PAGE_TIME_COUNTER; pageIntent.mode = PageIntent.MODE_SINGLE_INSTANCE; @@ -93,7 +83,8 @@ public class TimeCounterManager { public List getHistory() { return mActivityCounter.getHistory(); } - public CounterInfo getAppSetupInfo(){ - return mAppCounter.getAppSetupInfo(); + + public CounterInfo getAppSetupInfo() { + return mAppCounter.getAppSetupInfo(); } } diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/counter/ActivityCounter.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/counter/ActivityCounter.java index 80c0da77d9daf88e11e0e2e011dd5d6cc42f6c4a..fc970c824173468bb0b3a549203e454c274c64d9 100644 --- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/counter/ActivityCounter.java +++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/counter/ActivityCounter.java @@ -34,7 +34,7 @@ public class ActivityCounter { private String mCurrentActivity; private List mCounterInfos = new ArrayList<>(); - public void start() { + public void pause() { mStartTime = System.currentTimeMillis(); mPauseCostTime = 0; mRenderCostTime = 0; @@ -77,13 +77,18 @@ public class ActivityCounter { public void render() { mRenderStartTime = System.currentTimeMillis(); - Activity activity = DoraemonKit.getCurrentResumedActivity(); + final Activity activity = DoraemonKit.getCurrentResumedActivity(); if (activity != null && activity.getWindow() != null) { mCurrentActivity = activity.getClass().getSimpleName(); activity.getWindow().getDecorView().post(new Runnable() { @Override public void run() { - renderEnd(); + activity.getWindow().getDecorView().post(new Runnable() { + @Override + public void run() { + renderEnd(); + } + }); } }); } else { diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/counter/AppCounter.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/counter/AppCounter.java index 18d3b391f1122f21cd5111375c896402ba88bd13..5b588627e632d6bf35c5c1a7a3d7a2f11c6d26f6 100644 --- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/counter/AppCounter.java +++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/counter/AppCounter.java @@ -8,7 +8,6 @@ import com.didichuxing.doraemonkit.kit.timecounter.bean.CounterInfo; public class AppCounter { private long mStartTime; - private long mCost; private CounterInfo mCounterInfo = new CounterInfo(); public void start() { @@ -16,17 +15,12 @@ public class AppCounter { } public void end() { - mCost = System.currentTimeMillis() - mStartTime; mCounterInfo.title = "App Setup Cost"; - mCounterInfo.totalCost = mCost; + mCounterInfo.totalCost = System.currentTimeMillis() - mStartTime;; mCounterInfo.type = CounterInfo.TYPE_APP; mCounterInfo.time = System.currentTimeMillis(); } - public long getTime() { - return mCost; - } - public CounterInfo getAppSetupInfo() { return mCounterInfo; } diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/instrumentation/HandlerHooker.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/instrumentation/HandlerHooker.java new file mode 100755 index 0000000000000000000000000000000000000000..71f90d7e1a7008139836ea83ad6d8190276a4309 --- /dev/null +++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/instrumentation/HandlerHooker.java @@ -0,0 +1,76 @@ +package com.didichuxing.doraemonkit.kit.timecounter.instrumentation; + +import android.app.Application; +import android.os.Handler; + +import com.didichuxing.doraemonkit.util.LogHelper; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import me.weishu.reflection.Reflection; + +import static com.didichuxing.doraemonkit.BuildConfig.DEBUG; + +public class HandlerHooker { + private static final String TAG = "HandlerHooker"; + //是否已经hook成功 + private static boolean isHookSucceed = false; + + public static void doHook(Application app) { + try { + if (isHookSucceed()) { + return; + } + Reflection.unseal(app); + hookInstrumentation(); + isHookSucceed = true; + } catch (Exception e) { + if (DEBUG) { + LogHelper.e(TAG, e.toString()); + } + } + } + + + static boolean isHookSucceed() { + return isHookSucceed; + } + + private static void hookInstrumentation() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, NoSuchFieldException { + Class c = Class.forName("android.app.ActivityThread"); + Method currentActivityThread = c.getDeclaredMethod("currentActivityThread"); + boolean acc = currentActivityThread.isAccessible(); + if (!acc) { + currentActivityThread.setAccessible(true); + } + Object o = currentActivityThread.invoke(null); + if (!acc) { + currentActivityThread.setAccessible(acc); + } + Field f = c.getDeclaredField("mH"); + acc = f.isAccessible(); + if (!acc) { + f.setAccessible(true); + } + + Handler handler = (Handler) f.get(o); + if (!acc) { + f.setAccessible(acc); + } + + f = Handler.class.getDeclaredField("mCallback"); + acc = f.isAccessible(); + if (!acc) { + f.setAccessible(true); + } + Handler.Callback oldCallback = (Handler.Callback) f.get(handler); + ProxyHandlerCallback proxyMHCallback = new ProxyHandlerCallback(oldCallback,handler); + f.set(handler, proxyMHCallback); + if (!acc) { + f.setAccessible(acc); + } + } + +} \ No newline at end of file diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/instrumentation/ProxyHandlerCallback.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/instrumentation/ProxyHandlerCallback.java new file mode 100644 index 0000000000000000000000000000000000000000..43653dfc826d04661e705e3e1e772f9cb902deb1 --- /dev/null +++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/kit/timecounter/instrumentation/ProxyHandlerCallback.java @@ -0,0 +1,84 @@ +package com.didichuxing.doraemonkit.kit.timecounter.instrumentation; + +import android.os.Handler; +import android.os.Message; +import android.text.TextUtils; + +import com.didichuxing.doraemonkit.kit.timecounter.TimeCounterManager; +import com.didichuxing.doraemonkit.util.Reflector; + +/** + * @author: linjizong + * @date: 2019/6/3 + * @desc: + */ +class ProxyHandlerCallback implements Handler.Callback { + + public static final int LAUNCH_ACTIVITY = 100; + public static final int PAUSE_ACTIVITY = 101; + public static final int EXECUTE_TRANSACTION = 159; + public static final String LAUNCH_ITEM_CLASS = "android.app.servertransaction.ResumeActivityItem"; + public static final String PAUSE_ITEM_CLASS = "android.app.servertransaction.PauseActivityItem"; + + public final Handler.Callback mOldCallback; + public final Handler mHandler; + + ProxyHandlerCallback(Handler.Callback oldCallback, Handler handler) { + mOldCallback = oldCallback; + mHandler = handler; + } + + @Override + public boolean handleMessage(Message msg) { + int msgType = preDispatch(msg); + if (mOldCallback != null && mOldCallback.handleMessage(msg)) { + postDispatch(msgType); + return true; + } + mHandler.handleMessage(msg); + postDispatch(msgType); + return true; + } + + private int preDispatch(Message msg) { + switch (msg.what) { + case LAUNCH_ACTIVITY: + TimeCounterManager.get().onActivityLaunch(); + break; + case PAUSE_ACTIVITY: + TimeCounterManager.get().onActivityPause(); + break; + case EXECUTE_TRANSACTION: + return handlerActivity(msg); + } + return msg.what; + } + + private int handlerActivity(Message msg) { + Object obj = msg.obj; + + Object activityCallback = Reflector.QuietReflector.with(obj).method("getLifecycleStateRequest").call(); + if (activityCallback != null) { + String transactionName = activityCallback.getClass().getCanonicalName(); + if (TextUtils.equals(transactionName, LAUNCH_ITEM_CLASS)) { + TimeCounterManager.get().onActivityLaunch(); + return LAUNCH_ACTIVITY; + } else if (TextUtils.equals(transactionName, PAUSE_ITEM_CLASS)) { + TimeCounterManager.get().onActivityPause(); + return PAUSE_ACTIVITY; + } + } + return msg.what; + } + + private void postDispatch(int msgType) { + switch (msgType) { + case LAUNCH_ACTIVITY: + TimeCounterManager.get().onActivityLaunched(); + break; + case PAUSE_ACTIVITY: + TimeCounterManager.get().onActivityPaused(); + break; + } + } +} diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/FloatIconPage.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/FloatIconPage.java index ea90dfeae0864e30b8c84c3b9afc4f4b9d64bcec..b291df92fe608be548bba2546ac49a02637fb67e 100644 --- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/FloatIconPage.java +++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/FloatIconPage.java @@ -37,7 +37,11 @@ public class FloatIconPage extends BaseFloatPage implements TouchProxy.OnTouchEv getRootView().setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { - return mTouchProxy.onTouchEvent(v, event); + if (getRootView() != null) { + return mTouchProxy.onTouchEvent(v, event); + } else { + return false; + } } }); } diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/crash/CrashCaptureAdapter.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/crash/CrashCaptureAdapter.java deleted file mode 100644 index 1c97f68fb953f64cba99ca32f8f64fb03f1a6228..0000000000000000000000000000000000000000 --- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/crash/CrashCaptureAdapter.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.didichuxing.doraemonkit.ui.crash; - -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.BaseAdapter; -import android.widget.TextView; - -import com.didichuxing.doraemonkit.R; - -import java.io.File; -import java.util.List; - -public class CrashCaptureAdapter extends BaseAdapter { - private List files; - - public CrashCaptureAdapter(List files) { - this.files = files; - } - - @Override - public int getCount() { - return files.size(); - } - - @Override - public Object getItem(int position) { - return files.get(position); - } - - @Override - public long getItemId(int position) { - return position; - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - ViewHolder viewHolder; - if (convertView == null) { - convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.dk_item_crash_capture, parent, false); - viewHolder = new ViewHolder(convertView); - convertView.setTag(viewHolder); - } else { - viewHolder = (ViewHolder) convertView.getTag(); - } - viewHolder.setData(files.get(position).getName()); - return convertView; - } - - private class ViewHolder { - private TextView textView; - - public ViewHolder(View view) { - textView = view.findViewById(R.id.tv_crash_item); - } - - public void setData(String string) { - textView.setText(string); - } - } -} diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/crash/CrashHistoryAdapter.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/crash/CrashHistoryAdapter.java new file mode 100644 index 0000000000000000000000000000000000000000..d362743538dd2caa118bcd9665d7f29abe4e34ec --- /dev/null +++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/crash/CrashHistoryAdapter.java @@ -0,0 +1,55 @@ +package com.didichuxing.doraemonkit.ui.crash; + +import android.content.Context; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import com.didichuxing.doraemonkit.R; +import com.didichuxing.doraemonkit.kit.crash.CrashInfo; +import com.didichuxing.doraemonkit.ui.widget.recyclerview.AbsRecyclerAdapter; +import com.didichuxing.doraemonkit.ui.widget.recyclerview.AbsViewBinder; +import com.didichuxing.doraemonkit.util.FormatUtil; + +/** + * Created by wanglikun on 2019-06-12 + */ +public class CrashHistoryAdapter extends AbsRecyclerAdapter, CrashInfo> { + + public CrashHistoryAdapter(Context context) { + super(context); + } + + @Override + protected AbsViewBinder createViewHolder(View view, int viewType) { + return new CrashHistoryViewHolder(view); + } + + @Override + protected View createView(LayoutInflater inflater, ViewGroup parent, int viewType) { + return inflater.inflate(R.layout.dk_item_crash_history, parent, false); + } + + public static class CrashHistoryViewHolder extends AbsViewBinder { + private TextView mContent; + private TextView mTime; + + public CrashHistoryViewHolder(View view) { + super(view); + } + + @Override + protected void getViews() { + mContent = getView(R.id.content); + mTime = getView(R.id.time); + } + + @Override + public void bind(CrashInfo info) { + mContent.setText(Log.getStackTraceString(info.tr)); + mTime.setText(FormatUtil.format(info.time)); + } + } +} \ No newline at end of file diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/bottomview/AssociationView.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/bottomview/AssociationView.java new file mode 100644 index 0000000000000000000000000000000000000000..c40145201225b02cf88279bb8179cb4a5fdc62ce --- /dev/null +++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/bottomview/AssociationView.java @@ -0,0 +1,56 @@ +package com.didichuxing.doraemonkit.ui.widget.bottomview; + +import android.view.View; + +/** + * 可提交的view + * + * @author vinda + * @since 15/5/21 + */ +public abstract class AssociationView { + + private OnStateChangeListener onStateChangeListener; + + /** + * 提交 + */ + public abstract Object submit(); + + /** + * 取消 + */ + public abstract void cancel(); + + /** + * 获取视图 + * + * @return + */ + public abstract View getView(); + + /** + * 能否提交 + * + * @return + */ + public abstract boolean isCanSubmit(); + + public abstract void onShow(); + + public abstract void onHide(); + + + final void setOnStateChangeListener(OnStateChangeListener listener) { + onStateChangeListener = listener; + } + + final OnStateChangeListener getOnStateChangeListener() { + return onStateChangeListener; + } + + + interface OnStateChangeListener { + void onStateChanged(); + } +} diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/bottomview/BottomUpWindow.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/bottomview/BottomUpWindow.java new file mode 100644 index 0000000000000000000000000000000000000000..522b8233ee8a19479054455349d83ad1f29bced6 --- /dev/null +++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/bottomview/BottomUpWindow.java @@ -0,0 +1,178 @@ +package com.didichuxing.doraemonkit.ui.widget.bottomview; + +import android.content.Context; +import android.graphics.drawable.ColorDrawable; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.animation.Animation; +import android.view.animation.TranslateAnimation; +import android.widget.FrameLayout; +import android.widget.PopupWindow; + +import com.didichuxing.doraemonkit.R; + +/** + * 从底部向上弹出的选择器 + * + * @author vinda + * @since 15/5/21 + */ +public class BottomUpWindow extends PopupWindow { + private final String TAG = "BottomUpSelectWindow"; + private View thisView; + private View tv_submit; + private final View titleViiew; + private FrameLayout contentPanel; + private AssociationView associationView; + + private View ll_panel; + private View.OnClickListener onClickListener = new View.OnClickListener() { + @Override + public void onClick(View v) { + final int vid = v.getId(); + if (vid == R.id.tv_submit) { + Object submit = associationView.submit(); + if (mOnSubmitListener != null) { + mOnSubmitListener.submit(submit); + } + dismiss(); + } else if (vid == R.id.tv_cancel) { + cancel(); + } + } + + }; + + public BottomUpWindow(Context context) { + super(context); + LayoutInflater layoutInflater = LayoutInflater.from(context); + + thisView = layoutInflater.inflate(R.layout.dk_item_layout_bottom_up_select_window, null); + ll_panel = thisView.findViewById(R.id.ll_panel); + titleViiew = thisView.findViewById(R.id.tv_title); + + contentPanel = thisView.findViewById(R.id.content); + this.setContentView(thisView); + initView(); + + this.setWidth(ViewGroup.LayoutParams.MATCH_PARENT); + this.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT); + this.setFocusable(true); + this.setTouchable(true); + this.setOutsideTouchable(true); + + ColorDrawable dw = new ColorDrawable(0x80000000); + + this.setBackgroundDrawable(dw); + } + + private void initView() { + tv_submit = thisView.findViewById(R.id.tv_submit); + tv_submit.setOnClickListener(onClickListener); + thisView.findViewById(R.id.tv_cancel).setOnClickListener(onClickListener); + //点击在上方时关闭 + thisView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + cancel(); + + } + }); + } + + /** + * 设置中间内容的view + * + * @param view + */ + public BottomUpWindow setContent(AssociationView view) { + associationView = view; + contentPanel.removeAllViews(); + contentPanel.addView(associationView.getView()); + associationView.setOnStateChangeListener(new AssociationView.OnStateChangeListener() { + @Override + public void onStateChanged() { + tv_submit.setEnabled(associationView.isCanSubmit()); + } + }); + return this; + } + + @Override + public void dismiss() { + //动画 + TranslateAnimation animation = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0, + Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 1); + animation.setDuration(200); + animation.setAnimationListener(new Animation.AnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + + } + + @Override + public void onAnimationEnd(Animation animation) { + ll_panel.setVisibility(View.GONE); + dismissWindow(); + } + + @Override + public void onAnimationRepeat(Animation animation) { + + } + }); + ll_panel.startAnimation(animation); + if (associationView != null) { + associationView.onHide(); + } + } + + /** + * 隐藏整个窗口 + */ + private void dismissWindow() { + try { + super.dismiss(); + } catch (Throwable e) { + } + } + + private void cancel() { + associationView.cancel(); + dismiss(); + + if (mOnSubmitListener != null) { + mOnSubmitListener.cancel(); + } + } + + public BottomUpWindow show(View parent) { + this.showAtLocation(parent, Gravity.BOTTOM + | Gravity.CENTER_HORIZONTAL, 0, 0); + ll_panel.setVisibility(View.VISIBLE); + //动画 + TranslateAnimation animation = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0, + Animation.RELATIVE_TO_SELF, 1, Animation.RELATIVE_TO_SELF, 0); + animation.setDuration(200); + ll_panel.startAnimation(animation); + if (associationView != null) { + associationView.onShow(); + } + return this; + } + + private OnSubmitListener mOnSubmitListener; + + public void setOnSubmitListener(OnSubmitListener onSubmitListener) { + this.mOnSubmitListener = onSubmitListener; + } + + public interface OnSubmitListener { + + void submit(Object object); + + void cancel(); + } +} diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/bottomview/EditSpInputView.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/bottomview/EditSpInputView.java new file mode 100644 index 0000000000000000000000000000000000000000..e379667d99937db4a7931c69039f64be6ffddd87 --- /dev/null +++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/ui/widget/bottomview/EditSpInputView.java @@ -0,0 +1,54 @@ +package com.didichuxing.doraemonkit.ui.widget.bottomview; + +import android.content.Context; +import android.text.InputType; +import android.view.View; +import android.view.ViewGroup; +import android.widget.EditText; + +import com.didichuxing.doraemonkit.kit.fileexplorer.SpBean; + + +public class EditSpInputView extends AssociationView { + private final EditText editText; + private SpBean spBean; + + public EditSpInputView(Context context, SpBean spBean, int inputType) { + this.spBean = spBean; + editText = new EditText(context); + editText.setText(spBean.value.toString()); + editText.setInputType(inputType | InputType.TYPE_TEXT_FLAG_MULTI_LINE); + editText.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); + editText.setSelection(spBean.value.toString().length()); + } + + @Override + public Object submit() { + return spBean.toDefaultClass(editText.getText().toString()); + } + + @Override + public void cancel() { + + } + + @Override + public View getView() { + return editText; + } + + @Override + public boolean isCanSubmit() { + return true; + } + + @Override + public void onShow() { + + } + + @Override + public void onHide() { + + } +} diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/util/CacheUtils.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/util/CacheUtils.java index 7c5bfa03083c11ab70208a4e97b29806d8545479..5176c070f059448a09e15ca42a64d03600860385 100644 --- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/util/CacheUtils.java +++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/util/CacheUtils.java @@ -37,7 +37,7 @@ public class CacheUtils { return readObject(file); } - private static boolean saveObject(Serializable ser, File file) { + public static boolean saveObject(Serializable ser, File file) { FileOutputStream fos = null; ObjectOutputStream oos = null; try { @@ -67,7 +67,7 @@ public class CacheUtils { } } - private static Serializable readObject(File file) { + public static Serializable readObject(File file) { if (file == null || !file.exists() || file.isDirectory()) { return null; } diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/util/DatabaseUtil.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/util/DatabaseUtil.java index dddfc375a1e3ad0056966800514083d909003c16..47fc3f9f1162f809434c349056b6eb23b7ab34c2 100644 --- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/util/DatabaseUtil.java +++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/util/DatabaseUtil.java @@ -40,7 +40,7 @@ public class DatabaseUtil { Cursor cursor = database.query(tableName, null, null, null, null, null, null); int rowCount = cursor.getCount(); String[][] words = new String[strings.length][rowCount]; - for (int y = 0; y mType; + protected Object mCaller; + protected Constructor mConstructor; + protected Field mField; + protected Method mMethod; + + public static class ReflectedException extends Exception { + + public ReflectedException(String message) { + super(message); + } + public ReflectedException(String message, Throwable cause) { + super(message, cause); + } + + } + public static Reflector on(@NonNull String name) throws ReflectedException { + return on(name, true, Reflector.class.getClassLoader()); + } + + public static Reflector on(@NonNull String name, boolean initialize) throws ReflectedException { + return on(name, initialize, Reflector.class.getClassLoader()); + } + + public static Reflector on(@NonNull String name, boolean initialize, @Nullable ClassLoader loader) throws ReflectedException { + try { + return on(Class.forName(name, initialize, loader)); + } catch (Throwable e) { + throw new ReflectedException("Oops!", e); + } + } + + public static Reflector on(@NonNull Class type) { + Reflector reflector = new Reflector(); + reflector.mType = type; + return reflector; + } + + public static Reflector with(@NonNull Object caller) throws ReflectedException { + return on(caller.getClass()).bind(caller); + } + + protected Reflector() { + + } + + public Reflector constructor(@Nullable Class... parameterTypes) throws ReflectedException { + try { + mConstructor = mType.getDeclaredConstructor(parameterTypes); + mConstructor.setAccessible(true); + mField = null; + mMethod = null; + return this; + } catch (Throwable e) { + throw new ReflectedException("Oops!", e); + } + } + + @SuppressWarnings("unchecked") + public R newInstance(@Nullable Object ... initargs) throws ReflectedException { + if (mConstructor == null) { + throw new ReflectedException("Constructor was null!"); + } + try { + return (R) mConstructor.newInstance(initargs); + } catch (InvocationTargetException e) { + throw new ReflectedException("Oops!", e.getTargetException()); + } catch (Throwable e) { + throw new ReflectedException("Oops!", e); + } + } + + protected Object checked(@Nullable Object caller) throws ReflectedException { + if (caller == null || mType.isInstance(caller)) { + return caller; + } + throw new ReflectedException("Caller [" + caller + "] is not a instance of type [" + mType + "]!"); + } + + protected void check(@Nullable Object caller, @Nullable Member member, @NonNull String name) throws ReflectedException { + if (member == null) { + throw new ReflectedException(name + " was null!"); + } + if (caller == null && !Modifier.isStatic(member.getModifiers())) { + throw new ReflectedException("Need a caller!"); + } + checked(caller); + } + + public Reflector bind(@Nullable Object caller) throws ReflectedException { + mCaller = checked(caller); + return this; + } + + public Reflector unbind() { + mCaller = null; + return this; + } + + public Reflector field(@NonNull String name) throws ReflectedException { + try { + mField = findField(name); + mField.setAccessible(true); + mConstructor = null; + mMethod = null; + return this; + } catch (Throwable e) { + throw new ReflectedException("Oops!", e); + } + } + + protected Field findField(@NonNull String name) throws NoSuchFieldException { + try { + return mType.getField(name); + } catch (NoSuchFieldException e) { + for (Class cls = mType; cls != null; cls = cls.getSuperclass()) { + try { + return cls.getDeclaredField(name); + } catch (NoSuchFieldException ex) { + // Ignored + } + } + throw e; + } + } + + @SuppressWarnings("unchecked") + public R get() throws ReflectedException { + return get(mCaller); + } + + @SuppressWarnings("unchecked") + public R get(@Nullable Object caller) throws ReflectedException { + check(caller, mField, "Field"); + try { + return (R) mField.get(caller); + } catch (Throwable e) { + throw new ReflectedException("Oops!", e); + } + } + + public Reflector set(@Nullable Object value) throws ReflectedException { + return set(mCaller, value); + } + + public Reflector set(@Nullable Object caller, @Nullable Object value) throws ReflectedException { + check(caller, mField, "Field"); + try { + mField.set(caller, value); + return this; + } catch (Throwable e) { + throw new ReflectedException("Oops!", e); + } + } + + public Reflector method(@NonNull String name, @Nullable Class... parameterTypes) throws ReflectedException { + try { + mMethod = findMethod(name, parameterTypes); + mMethod.setAccessible(true); + mConstructor = null; + mField = null; + return this; + } catch (NoSuchMethodException e) { + throw new ReflectedException("Oops!", e); + } + } + + protected Method findMethod(@NonNull String name, @Nullable Class... parameterTypes) throws NoSuchMethodException { + try { + return mType.getMethod(name, parameterTypes); + } catch (NoSuchMethodException e) { + for (Class cls = mType; cls != null; cls = cls.getSuperclass()) { + try { + return cls.getDeclaredMethod(name, parameterTypes); + } catch (NoSuchMethodException ex) { + // Ignored + } + } + throw e; + } + } + + public R call(@Nullable Object... args) throws ReflectedException { + return callByCaller(mCaller, args); + } + + @SuppressWarnings("unchecked") + public R callByCaller(@Nullable Object caller, @Nullable Object... args) throws ReflectedException { + check(caller, mMethod, "Method"); + try { + return (R) mMethod.invoke(caller, args); + } catch (InvocationTargetException e) { + throw new ReflectedException("Oops!", e.getTargetException()); + } catch (Throwable e) { + throw new ReflectedException("Oops!", e); + } + } + + public static class QuietReflector extends Reflector { + + protected Throwable mIgnored; + + public static QuietReflector on(@NonNull String name) { + return on(name, true, QuietReflector.class.getClassLoader()); + } + + public static QuietReflector on(@NonNull String name, boolean initialize) { + return on(name, initialize, QuietReflector.class.getClassLoader()); + } + + public static QuietReflector on(@NonNull String name, boolean initialize, @Nullable ClassLoader loader) { + Class cls = null; + try { + cls = Class.forName(name, initialize, loader); + return on(cls, null); + } catch (Throwable e) { +// Log.w(LOG_TAG, "Oops!", e); + return on(cls, e); + } + } + + public static QuietReflector on(@Nullable Class type) { + return on(type, (type == null) ? new ReflectedException("Type was null!") : null); + } + + private static QuietReflector on(@Nullable Class type, @Nullable Throwable ignored) { + QuietReflector reflector = new QuietReflector(); + reflector.mType = type; + reflector.mIgnored = ignored; + return reflector; + } + + public static QuietReflector with(@Nullable Object caller) { + if (caller == null) { + return on((Class) null); + } + return on(caller.getClass()).bind(caller); + } + + protected QuietReflector() { + + } + + public Throwable getIgnored() { + return mIgnored; + } + + protected boolean skip() { + return skipAlways() || mIgnored != null; + } + + protected boolean skipAlways() { + return mType == null; + } + + @Override + public QuietReflector constructor(@Nullable Class... parameterTypes) { + if (skipAlways()) { + return this; + } + try { + mIgnored = null; + super.constructor(parameterTypes); + } catch (Throwable e) { + mIgnored = e; +// Log.w(LOG_TAG, "Oops!", e); + } + return this; + } + + @Override + public R newInstance(@Nullable Object... initargs) { + if (skip()) { + return null; + } + try { + mIgnored = null; + return super.newInstance(initargs); + } catch (Throwable e) { + mIgnored = e; +// Log.w(LOG_TAG, "Oops!", e); + } + return null; + } + + @Override + public QuietReflector bind(@Nullable Object obj) { + if (skipAlways()) { + return this; + } + try { + mIgnored = null; + super.bind(obj); + } catch (Throwable e) { + mIgnored = e; +// Log.w(LOG_TAG, "Oops!", e); + } + return this; + } + + @Override + public QuietReflector unbind() { + super.unbind(); + return this; + } + + @Override + public QuietReflector field(@NonNull String name) { + if (skipAlways()) { + return this; + } + try { + mIgnored = null; + super.field(name); + } catch (Throwable e) { + mIgnored = e; +// Log.w(LOG_TAG, "Oops!", e); + } + return this; + } + + @Override + public R get() { + if (skip()) { + return null; + } + try { + mIgnored = null; + return super.get(); + } catch (Throwable e) { + mIgnored = e; +// Log.w(LOG_TAG, "Oops!", e); + } + return null; + } + + @Override + public R get(@Nullable Object caller) { + if (skip()) { + return null; + } + try { + mIgnored = null; + return super.get(caller); + } catch (Throwable e) { + mIgnored = e; +// Log.w(LOG_TAG, "Oops!", e); + } + return null; + } + + @Override + public QuietReflector set(@Nullable Object value) { + if (skip()) { + return this; + } + try { + mIgnored = null; + super.set(value); + } catch (Throwable e) { + mIgnored = e; +// Log.w(LOG_TAG, "Oops!", e); + } + return this; + } + + @Override + public QuietReflector set(@Nullable Object caller, @Nullable Object value) { + if (skip()) { + return this; + } + try { + mIgnored = null; + super.set(caller, value); + } catch (Throwable e) { + mIgnored = e; +// Log.w(LOG_TAG, "Oops!", e); + } + return this; + } + + @Override + public QuietReflector method(@NonNull String name, @Nullable Class... parameterTypes) { + if (skipAlways()) { + return this; + } + try { + mIgnored = null; + super.method(name, parameterTypes); + } catch (Throwable e) { + mIgnored = e; +// Log.w(LOG_TAG, "Oops!", e); + } + return this; + } + + @Override + public R call(@Nullable Object... args) { + if (skip()) { + return null; + } + try { + mIgnored = null; + return super.call(args); + } catch (Throwable e) { + mIgnored = e; +// Log.w(LOG_TAG, "Oops!", e); + } + return null; + } + + @Override + public R callByCaller(@Nullable Object caller, @Nullable Object... args) { + if (skip()) { + return null; + } + try { + mIgnored = null; + return super.callByCaller(caller, args); + } catch (Throwable e) { + mIgnored = e; +// Log.w(LOG_TAG, "Oops!", e); + } + return null; + } + } +} \ No newline at end of file diff --git a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/util/SharedPrefsUtil.java b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/util/SharedPrefsUtil.java index b47528638b3689dd3515e2b5a975e2289c45e498..5da90ec6aaed949e0503310570ce39e69dd95bad 100644 --- a/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/util/SharedPrefsUtil.java +++ b/Android/doraemonkit/src/main/java/com/didichuxing/doraemonkit/util/SharedPrefsUtil.java @@ -2,6 +2,7 @@ package com.didichuxing.doraemonkit.util; import android.content.Context; import android.content.SharedPreferences; +import android.support.annotation.Nullable; /** * Created by wanglikun on 2018/9/14. @@ -11,33 +12,62 @@ public class SharedPrefsUtil { private static final String SHARED_PREFS_DORAEMON = "shared_prefs_doraemon"; private static SharedPreferences getSharedPrefs(Context context) { - return context.getSharedPreferences(SHARED_PREFS_DORAEMON, Context.MODE_PRIVATE); + return getSharedPrefs(context, SHARED_PREFS_DORAEMON); } - public static void putString(Context context, String key, String value) { - getSharedPrefs(context).edit().putString(key, value).apply(); + @Nullable + public static SharedPreferences getSharedPrefs(Context context, String name) { + return context.getSharedPreferences(name, Context.MODE_PRIVATE); } - public static String getString(Context context,String key, String defVal) { + public static String getString(Context context, String key, String defVal) { return getSharedPrefs(context).getString(key, defVal); } + public static void putString(Context context, String key, String value) { + putString(context, SHARED_PREFS_DORAEMON, key, value); + } + + public static void putString(Context context, String table, String key, String value) { + getSharedPrefs(context, table).edit().putString(key, value).apply(); + } + public static void putBoolean(Context context, String key, boolean value) { if (context == null) { return; } - getSharedPrefs(context).edit().putBoolean(key, value).apply(); + putBoolean(context, SHARED_PREFS_DORAEMON, key, value); + } + + public static void putBoolean(Context context, String table, String key, boolean value) { + getSharedPrefs(context, table).edit().putBoolean(key, value).apply(); } - public static boolean getBoolean(Context context,String key, boolean defVal) { + public static boolean getBoolean(Context context, String key, boolean defVal) { return context != null && getSharedPrefs(context).getBoolean(key, defVal); } public static void putInt(Context context, String key, int value) { - getSharedPrefs(context).edit().putInt(key, value).apply(); + putInt(context, SHARED_PREFS_DORAEMON, key, value); } - public static int getInt(Context context,String key, int defVal) { + public static void putInt(Context context, String table, String key, Integer value) { + getSharedPrefs(context, table).edit().putInt(key, value).apply(); + } + + public static int getInt(Context context, String key, int defVal) { return getSharedPrefs(context).getInt(key, defVal); } + + public static void putFloat(Context context, String table, String key, Float value) { + getSharedPrefs(context, table).edit().putFloat(key, value).apply(); + } + + public static void putFloat(Context context, String key, Float value) { + getSharedPrefs(context, SHARED_PREFS_DORAEMON).edit().putFloat(key, value).apply(); + } + + public static void putLong(Context context, String table, String key, Long value) { + getSharedPrefs(context, table).edit().putLong(key, value).apply(); + } } diff --git a/Android/doraemonkit/src/main/res/drawable-xxhdpi/dk_sp_modify.png b/Android/doraemonkit/src/main/res/drawable-xxhdpi/dk_sp_modify.png new file mode 100644 index 0000000000000000000000000000000000000000..3e347a8cd338c964eee0dcc07c9478605b89c3da Binary files /dev/null and b/Android/doraemonkit/src/main/res/drawable-xxhdpi/dk_sp_modify.png differ diff --git a/Android/doraemonkit/src/main/res/layout/dk_fragment_crash_capture.xml b/Android/doraemonkit/src/main/res/layout/dk_fragment_crash_capture_detail.xml similarity index 65% rename from Android/doraemonkit/src/main/res/layout/dk_fragment_crash_capture.xml rename to Android/doraemonkit/src/main/res/layout/dk_fragment_crash_capture_detail.xml index 2d3fb90fe7aa993cdbda72a9e789e86b9a088480..9d6326592fe545d7ba39cc595a22340ac279a063 100644 --- a/Android/doraemonkit/src/main/res/layout/dk_fragment_crash_capture.xml +++ b/Android/doraemonkit/src/main/res/layout/dk_fragment_crash_capture_detail.xml @@ -17,11 +17,19 @@ - + android:layout_height="match_parent" /> + + diff --git a/Android/doraemonkit/src/main/res/layout/dk_fragment_sp_show.xml b/Android/doraemonkit/src/main/res/layout/dk_fragment_sp_show.xml index 65687f8adfd261e4ecdfbe20d14ae01cd6dfef51..9ed29b5b482958f9fdec72242e9bdeb3cae9a055 100644 --- a/Android/doraemonkit/src/main/res/layout/dk_fragment_sp_show.xml +++ b/Android/doraemonkit/src/main/res/layout/dk_fragment_sp_show.xml @@ -21,29 +21,4 @@ android:layout_height="0dp" android:layout_weight="10" /> - - - - - - - - \ No newline at end of file diff --git a/Android/doraemonkit/src/main/res/layout/dk_item_crash_capture.xml b/Android/doraemonkit/src/main/res/layout/dk_item_crash_capture.xml deleted file mode 100644 index fc21215f8cda51130fdc29417d411efb153a9d7c..0000000000000000000000000000000000000000 --- a/Android/doraemonkit/src/main/res/layout/dk_item_crash_capture.xml +++ /dev/null @@ -1,9 +0,0 @@ - - diff --git a/Android/doraemonkit/src/main/res/layout/dk_item_crash_history.xml b/Android/doraemonkit/src/main/res/layout/dk_item_crash_history.xml new file mode 100644 index 0000000000000000000000000000000000000000..28cd9b3fe3bd1334fd1f5e3df3e2d6b024ea4694 --- /dev/null +++ b/Android/doraemonkit/src/main/res/layout/dk_item_crash_history.xml @@ -0,0 +1,21 @@ + + + + + + + + + + \ No newline at end of file diff --git a/Android/doraemonkit/src/main/res/layout/dk_item_layout_bottom_up_select_window.xml b/Android/doraemonkit/src/main/res/layout/dk_item_layout_bottom_up_select_window.xml new file mode 100644 index 0000000000000000000000000000000000000000..377b7ef174f4bed78203b9e0a9c23b92f9776bcb --- /dev/null +++ b/Android/doraemonkit/src/main/res/layout/dk_item_layout_bottom_up_select_window.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Android/doraemonkit/src/main/res/layout/dk_item_setting.xml b/Android/doraemonkit/src/main/res/layout/dk_item_setting.xml index 7755d62a504b3c61565f7552d02d21153e3d0427..ce1c3efb5fbd14800b288d2d3fa0aec495595633 100644 --- a/Android/doraemonkit/src/main/res/layout/dk_item_setting.xml +++ b/Android/doraemonkit/src/main/res/layout/dk_item_setting.xml @@ -40,7 +40,7 @@ android:layout_centerVertical="true" android:layout_alignWithParentIfMissing="true" android:layout_toLeftOf="@id/right_icon" - android:layout_marginRight="5dp" + android:layout_marginRight="15dp" android:text="@string/dk_app_name" android:visibility="gone"/> diff --git a/Android/doraemonkit/src/main/res/layout/dk_item_sp_input.xml b/Android/doraemonkit/src/main/res/layout/dk_item_sp_input.xml index 693a30c7eb6e93eb96177ab847e96105a5c03d18..6839821b6e043abafe4d39bbad70835a916ac2b6 100644 --- a/Android/doraemonkit/src/main/res/layout/dk_item_sp_input.xml +++ b/Android/doraemonkit/src/main/res/layout/dk_item_sp_input.xml @@ -1,16 +1,17 @@ + android:layout_height="40dp"> + android:layout_height="wrap_content" + android:layout_marginRight="5dp"> - - \ No newline at end of file diff --git a/Android/doraemonkit/src/main/res/values-en-rUS/strings.xml b/Android/doraemonkit/src/main/res/values-en-rUS/strings.xml index d30c1a8ad857090f5314e461b4a3b268edff97e0..97b96b323630c723bb8893aa96d4b7b478a6743f 100644 --- a/Android/doraemonkit/src/main/res/values-en-rUS/strings.xml +++ b/Android/doraemonkit/src/main/res/values-en-rUS/strings.xml @@ -173,5 +173,8 @@ view statistics page data Loading... + Please authorize permissions + Clear system data + Please authorize permissions diff --git a/Android/doraemonkit/src/main/res/values-zh-rCN/strings.xml b/Android/doraemonkit/src/main/res/values-zh-rCN/strings.xml index 79fa8ced1eaddb640d3079037eb732502a4f81fd..3383a5ce2d1a672843d5e95bece743693c08eadb 100644 --- a/Android/doraemonkit/src/main/res/values-zh-rCN/strings.xml +++ b/Android/doraemonkit/src/main/res/values-zh-rCN/strings.xml @@ -172,4 +172,7 @@ 查看统计数据 页面数据 日志加载中... + 请授权读写权限,避免crash文件丢失 + 清除系统资料 + 请进行授权才可以使用该功能 diff --git a/Android/doraemonkit/src/main/res/values-zh-rTW/strings.xml b/Android/doraemonkit/src/main/res/values-zh-rTW/strings.xml index 21d9869ef3d1c4c1e59e30b0df795f45f4082524..3607ee26b702fd8cbbf2d588121f09e60deb28ce 100644 --- a/Android/doraemonkit/src/main/res/values-zh-rTW/strings.xml +++ b/Android/doraemonkit/src/main/res/values-zh-rTW/strings.xml @@ -154,4 +154,19 @@ Message Body 鏈接 總封包數 + 取消 + 確認 + 請授權讀寫權限,避免crash文件丟失 + 添加 + 刪除 + 請進行授權才可以使用該功能 + 失敗 + 自定義 + 提示 + 分享 + 開始測試 + 結束測試 + 成功 + 提交 + 日誌加載中... \ No newline at end of file diff --git a/Android/doraemonkit/src/main/res/values/strings.xml b/Android/doraemonkit/src/main/res/values/strings.xml index 3599ffdc56d992cef0f641db07e30922c8c636b8..2c35dea032eaed293e384ef70f34b0628f6ab5d9 100644 --- a/Android/doraemonkit/src/main/res/values/strings.xml +++ b/Android/doraemonkit/src/main/res/values/strings.xml @@ -92,6 +92,7 @@ Crash日志收集开关 一键清理Crash日志 Crash日志列表 + 请授权读写权限,避免crash文件丢失 模拟弱网开关 断网 @@ -185,5 +186,6 @@ 查看统计数据 页面数据 日志加载中... + 清除系统资料 diff --git a/Android/doraemonkit/upload.gradle b/Android/doraemonkit/upload.gradle index ccc6ee5b1f96feb8487f7d5ab225263df8a33295..896758fed8f4e006395b24d28170ce6b1eb05c3d 100644 --- a/Android/doraemonkit/upload.gradle +++ b/Android/doraemonkit/upload.gradle @@ -3,7 +3,7 @@ apply plugin: 'com.novoda.bintray-release' publish { def groupProjectID = 'com.didichuxing.doraemonkit' def artifactProjectID = 'doraemonkit' - def publishVersionID = '1.1.7' + def publishVersionID = '1.1.8' userOrg = 'doraemonkit' repoName = 'DoraemonKit' diff --git a/Android/compiler-plugin/.gitignore b/Android/doraemonkit_weex/.gitignore similarity index 100% rename from Android/compiler-plugin/.gitignore rename to Android/doraemonkit_weex/.gitignore diff --git a/Android/doraemonkit_weex/build.gradle b/Android/doraemonkit_weex/build.gradle new file mode 100644 index 0000000000000000000000000000000000000000..524d0315c7e534eb8bbe0798b0bf98721172a5f5 --- /dev/null +++ b/Android/doraemonkit_weex/build.gradle @@ -0,0 +1,38 @@ +apply plugin: 'com.android.library' +apply from: './upload.gradle' + +android { + compileSdkVersion 26 + + defaultConfig { + minSdkVersion 16 + targetSdkVersion 26 + versionCode 1 + versionName "1.0" + + lintOptions { + abortOnError false + } + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + + implementation 'com.android.support:appcompat-v7:26.1.0' + implementation "com.android.support:design:26.0.2" + + debugImplementation project(':doraemonkit') + releaseImplementation 'com.didichuxing.doraemonkit:doraemonkit:1.1.8' + + implementation 'com.taobao.android:weex_inspector:0.18.10' + implementation "com.taobao.android:weex_sdk:0.24.0" +} diff --git a/Android/compiler-plugin/proguard-rules.pro b/Android/doraemonkit_weex/proguard-rules.pro similarity index 100% rename from Android/compiler-plugin/proguard-rules.pro rename to Android/doraemonkit_weex/proguard-rules.pro diff --git a/Android/doraemonkit_weex/src/main/AndroidManifest.xml b/Android/doraemonkit_weex/src/main/AndroidManifest.xml new file mode 100644 index 0000000000000000000000000000000000000000..8e4161953f88de1f740fcb2d4f95e1ed4633a0ea --- /dev/null +++ b/Android/doraemonkit_weex/src/main/AndroidManifest.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + diff --git a/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/DKWeexInstance.java b/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/DKWeexInstance.java new file mode 100644 index 0000000000000000000000000000000000000000..19a68b8742313d3339358c3aa029d55b80a7ba8d --- /dev/null +++ b/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/DKWeexInstance.java @@ -0,0 +1,41 @@ +package com.didichuxing.doraemonkit.weex; + +import android.app.Application; + +import com.didichuxing.doraemonkit.DoraemonKit; +import com.didichuxing.doraemonkit.kit.IKit; +import com.didichuxing.doraemonkit.weex.log.WeexLogKit; +import com.didichuxing.doraemonkit.weex.devtool.DevToolKit; +import com.didichuxing.doraemonkit.weex.info.WeexInfoKit; +import com.didichuxing.doraemonkit.weex.storage.StorageKit; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author haojianglong + * @date 2019-06-11 + */ +public class DKWeexInstance { + + private DKWeexInstance() { + } + + public static DKWeexInstance getInstance() { + return SingleHolder.sInstance; + } + + private static class SingleHolder { + private static final DKWeexInstance sInstance = new DKWeexInstance(); + } + + public void init(Application app) { + List bizKits = new ArrayList<>(); + bizKits.add(new WeexLogKit()); + bizKits.add(new StorageKit()); + bizKits.add(new WeexInfoKit()); + bizKits.add(new DevToolKit()); + DoraemonKit.install(app, bizKits); + } + +} diff --git a/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/common/DKCommonActivity.java b/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/common/DKCommonActivity.java new file mode 100644 index 0000000000000000000000000000000000000000..bcd8b7662f7c0994a5f009fa638bed814f919da3 --- /dev/null +++ b/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/common/DKCommonActivity.java @@ -0,0 +1,37 @@ +package com.didichuxing.doraemonkit.weex.common; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.support.annotation.Nullable; + +import com.didichuxing.doraemonkit.ui.base.BaseActivity; +import com.didichuxing.doraemonkit.ui.base.BaseFragment; + +/** + * @author haojianglong + * @date 2019-06-18 + */ +public class DKCommonActivity extends BaseActivity { + + private static final String CLASSNAME = "className"; + + public static void startWith(Context context, Class clazz) { + Intent intent = new Intent(context, DKCommonActivity.class); + intent.putExtra(CLASSNAME, clazz); + context.startActivity(intent); + } + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + Bundle bundle = getIntent().getExtras(); + if (bundle == null) { + finish(); + return; + } + Class clazz = (Class) getIntent().getSerializableExtra(CLASSNAME); + showContent(clazz); + } + +} diff --git a/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/devtool/DevToolActivity.java b/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/devtool/DevToolActivity.java new file mode 100644 index 0000000000000000000000000000000000000000..76da3b6c3393a680611306d7d7b37b6e05475c11 --- /dev/null +++ b/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/devtool/DevToolActivity.java @@ -0,0 +1,109 @@ +package com.didichuxing.doraemonkit.weex.devtool; + +import android.Manifest; +import android.app.Activity; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v7.app.AppCompatActivity; +import android.text.TextUtils; +import android.widget.Toast; + +import com.didichuxing.doraemonkit.zxing.activity.CaptureActivity; +import com.taobao.weex.WXEnvironment; +import com.taobao.weex.WXSDKEngine; + +/** + * @author haojianglong + * @date 2019-06-25 + */ +public class DevToolActivity extends AppCompatActivity { + + private final int REQUEST_CODE_CAMERA = 0x100; + private final int REQUEST_CODE_SCAN = 0x101; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + if (checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_DENIED) { + String[] permissions = {Manifest.permission.CAMERA}; + requestPermissions(permissions, REQUEST_CODE_CAMERA); + } else { + startScan(); + } + } else { + startScan(); + } + } + + private void startScan() { + Intent intent = new Intent(this, DevToolScanActivity.class); + startActivityForResult(intent, REQUEST_CODE_SCAN); + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + if (requestCode == REQUEST_CODE_CAMERA) { + if (permissions.length > 0) { + for (int i = 0; i < permissions.length; i++) { + if (Manifest.permission.CAMERA.equals(permissions[i]) && + grantResults[i] == PackageManager.PERMISSION_GRANTED) { + startScan(); + return; + } + } + } + finish(); + } + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == REQUEST_CODE_SCAN && resultCode == Activity.RESULT_OK) { + if (data != null && data.hasExtra(CaptureActivity.INTENT_EXTRA_KEY_QR_SCAN)) { + String code = data.getStringExtra(CaptureActivity.INTENT_EXTRA_KEY_QR_SCAN); + if (!TextUtils.isEmpty(code)) { + try { + Uri uri = Uri.parse(code); + handleScanResult(uri); + } catch (Exception e) { + e.printStackTrace(); + } finally { + finish(); + } + } else { + handleNoResult(); + } + } else { + handleNoResult(); + } + } else { + handleNoResult(); + } + } + + private void handleNoResult() { + Toast.makeText(getApplicationContext(), "没有扫描到任何内容>_<", Toast.LENGTH_SHORT); + finish(); + } + + private void handleScanResult(Uri uri) { + if (WXEnvironment.isApkDebugable()) { + String devToolUrl = uri.getQueryParameter("_wx_devtool"); + if (!TextUtils.isEmpty(devToolUrl)) { + WXEnvironment.sRemoteDebugProxyUrl = devToolUrl; + WXEnvironment.sDebugServerConnectable = true; + WXSDKEngine.reload(getApplicationContext(), false); + } + } + finish(); + } + +} diff --git a/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/devtool/DevToolKit.java b/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/devtool/DevToolKit.java new file mode 100644 index 0000000000000000000000000000000000000000..ffca29e25886f153bbbc307e4261490f208dbe06 --- /dev/null +++ b/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/devtool/DevToolKit.java @@ -0,0 +1,42 @@ +package com.didichuxing.doraemonkit.weex.devtool; + +import android.content.Context; +import android.content.Intent; + +import com.didichuxing.doraemonkit.kit.Category; +import com.didichuxing.doraemonkit.kit.IKit; +import com.didichuxing.doraemonkit.weex.R; + +/** + * @author haojianglong + * @date 2019-06-11 + */ +public class DevToolKit implements IKit { + + @Override + public int getCategory() { + return Category.BIZ; + } + + @Override + public int getName() { + return R.string.dk_dev_tool_name; + } + + @Override + public int getIcon() { + return R.drawable.dk_custom; + } + + @Override + public void onClick(Context context) { + Intent intent = new Intent(context, DevToolActivity.class); + context.startActivity(intent); + } + + @Override + public void onAppInit(Context context) { + + } + +} diff --git a/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/devtool/DevToolScanActivity.java b/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/devtool/DevToolScanActivity.java new file mode 100644 index 0000000000000000000000000000000000000000..2e2f7d4247b55883445c32b46b3e90b5defa13fc --- /dev/null +++ b/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/devtool/DevToolScanActivity.java @@ -0,0 +1,46 @@ +package com.didichuxing.doraemonkit.weex.devtool; + +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; + +import com.didichuxing.doraemonkit.ui.widget.titlebar.HomeTitleBar; +import com.didichuxing.doraemonkit.weex.R; +import com.didichuxing.doraemonkit.zxing.activity.CaptureActivity; + +/** + * @author haojianglong + * @date 2019-06-18 + */ +public class DevToolScanActivity extends CaptureActivity { + + @Override + public void setContentView(View view) { + super.setContentView(view); + initTitleBar(); + } + + @Override + public void setContentView(int layoutResID) { + super.setContentView(layoutResID); + initTitleBar(); + } + + private void initTitleBar() { + HomeTitleBar homeTitleBar = new HomeTitleBar(this); + homeTitleBar.setBackgroundColor(getResources().getColor(R.color.foreground_wtf)); + homeTitleBar.setTitle(getResources().getString(R.string.dk_dev_tool_title)); + homeTitleBar.setIcon(R.drawable.dk_close_icon); + homeTitleBar.setListener(new HomeTitleBar.OnTitleBarClickListener() { + @Override + public void onRightClick() { + finish(); + } + }); + FrameLayout.LayoutParams params = + new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, + (int) getResources().getDimension(R.dimen.dk_home_title_height)); + ((FrameLayout) findViewById(android.R.id.content)).addView(homeTitleBar, params); + } + +} diff --git a/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/info/WeexInfo.java b/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/info/WeexInfo.java new file mode 100644 index 0000000000000000000000000000000000000000..bff82e30ab2979027d32e645bf53d7ed0c372748 --- /dev/null +++ b/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/info/WeexInfo.java @@ -0,0 +1,18 @@ +package com.didichuxing.doraemonkit.weex.info; + +/** + * @author haojianglong + * @date 2019-06-25 + */ +public class WeexInfo { + + public String key; + + public String value; + + public WeexInfo(String key, String value) { + this.key = key; + this.value = value; + } + +} diff --git a/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/info/WeexInfoAdapter.java b/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/info/WeexInfoAdapter.java new file mode 100644 index 0000000000000000000000000000000000000000..63a05e70f0472d082beced7656a001db9e778cfa --- /dev/null +++ b/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/info/WeexInfoAdapter.java @@ -0,0 +1,85 @@ +package com.didichuxing.doraemonkit.weex.info; + +import android.content.Context; +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.didichuxing.doraemonkit.weex.R; + +import java.util.List; + +/** + * @author haojianglong + * @date 2019-06-25 + */ +public class WeexInfoAdapter extends BaseAdapter { + + private Context mContext; + + private List mWeexInfos; + + public void setWeexInfos(List infos) { + this.mWeexInfos = infos; + } + + public WeexInfoAdapter(Context context) { + this.mContext = context; + } + + @Override + public int getCount() { + return mWeexInfos.size(); + } + + @Override + public Object getItem(int position) { + return mWeexInfos.get(position); + } + + @Override + public long getItemId(int position) { + return 0; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + if (convertView == null) { + convertView = LayoutInflater.from(mContext) + .inflate(R.layout.dk_fragment_info_item, null); + } + ViewHolder viewHolder; + if (convertView.getTag() == null) { + viewHolder = new ViewHolder(); + viewHolder.keyText = convertView.findViewById(R.id.info_item_key); + viewHolder.valueText = convertView.findViewById(R.id.info_item_value); + convertView.setTag(viewHolder); + } else { + viewHolder = (ViewHolder) convertView.getTag(); + } + setText(viewHolder.keyText, mWeexInfos.get(position).key); + setText(viewHolder.valueText, mWeexInfos.get(position).value); + convertView.setLayoutParams(new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, + (int) mContext.getResources().getDimension(R.dimen.dk_title_height))); + return convertView; + } + + private void setText(TextView textView, String text) { + if (TextUtils.isEmpty(text)) { + textView.setVisibility(View.GONE); + } else { + textView.setVisibility(View.VISIBLE); + textView.setText(text); + } + } + + class ViewHolder { + TextView keyText; + TextView valueText; + } + +} diff --git a/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/info/WeexInfoFragment.java b/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/info/WeexInfoFragment.java new file mode 100644 index 0000000000000000000000000000000000000000..0b030aecc736516d5a4933eca902bf8470afe4ae --- /dev/null +++ b/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/info/WeexInfoFragment.java @@ -0,0 +1,46 @@ +package com.didichuxing.doraemonkit.weex.info; + +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.view.View; +import android.widget.ListView; + +import com.didichuxing.doraemonkit.ui.base.BaseFragment; +import com.didichuxing.doraemonkit.ui.widget.titlebar.HomeTitleBar; +import com.didichuxing.doraemonkit.weex.R; + +/** + * @author haojianglong + * @date 2019-06-18 + */ +public class WeexInfoFragment extends BaseFragment { + + private WeexInfoAdapter mAdapter; + + @Override + protected int onRequestLayout() { + return R.layout.dk_fragment_info; + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + initView(); + } + + private void initView() { + HomeTitleBar titleBar = findViewById(R.id.title_bar); + titleBar.setListener(new HomeTitleBar.OnTitleBarClickListener() { + @Override + public void onRightClick() { + getActivity().finish(); + } + }); + ListView listView = findViewById(R.id.info_list); + mAdapter = new WeexInfoAdapter(getContext()); + mAdapter.setWeexInfos(WeexInfoHacker.getWeexInfos()); + listView.setAdapter(mAdapter); + } + +} diff --git a/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/info/WeexInfoHacker.java b/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/info/WeexInfoHacker.java new file mode 100644 index 0000000000000000000000000000000000000000..83339c7efd57ceb1bc8db437270a59bd0092548c --- /dev/null +++ b/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/info/WeexInfoHacker.java @@ -0,0 +1,27 @@ +package com.didichuxing.doraemonkit.weex.info; + +import com.taobao.weex.WXEnvironment; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * @author haojianglong + * @date 2019-06-25 + */ +public class WeexInfoHacker { + + public static List getWeexInfos() { + List infos = new ArrayList<>(); + if (WXEnvironment.getConfig() != null) { + Set> entrySet = WXEnvironment.getConfig().entrySet(); + for (Map.Entry entry : entrySet) { + infos.add(new WeexInfo(entry.getKey(), entry.getValue())); + } + } + return infos; + } + +} diff --git a/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/info/WeexInfoKit.java b/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/info/WeexInfoKit.java new file mode 100644 index 0000000000000000000000000000000000000000..b70543acb777538be97238896614e768642ca476 --- /dev/null +++ b/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/info/WeexInfoKit.java @@ -0,0 +1,41 @@ +package com.didichuxing.doraemonkit.weex.info; + +import android.content.Context; + +import com.didichuxing.doraemonkit.kit.Category; +import com.didichuxing.doraemonkit.kit.IKit; +import com.didichuxing.doraemonkit.weex.R; +import com.didichuxing.doraemonkit.weex.common.DKCommonActivity; + +/** + * @author haojianglong + * @date 2019-06-11 + */ +public class WeexInfoKit implements IKit { + + @Override + public int getCategory() { + return Category.BIZ; + } + + @Override + public int getName() { + return R.string.dk_weex_info_name; + } + + @Override + public int getIcon() { + return R.drawable.dk_sys_info; + } + + @Override + public void onClick(Context context) { + DKCommonActivity.startWith(context, WeexInfoFragment.class); + } + + @Override + public void onAppInit(Context context) { + + } + +} diff --git a/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/log/WeexLogInfoFragment.java b/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/log/WeexLogInfoFragment.java new file mode 100644 index 0000000000000000000000000000000000000000..a11a308b53c0d5d34b1c727b1951f17adfd1d92d --- /dev/null +++ b/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/log/WeexLogInfoFragment.java @@ -0,0 +1,38 @@ +package com.didichuxing.doraemonkit.weex.log; + +import android.os.Bundle; +import android.support.annotation.Nullable; + +import com.didichuxing.doraemonkit.ui.base.BaseFragment; +import com.didichuxing.doraemonkit.ui.base.FloatPageManager; +import com.didichuxing.doraemonkit.ui.base.PageIntent; + +/** + * @author haojianglong + * @date 2019-06-25 + */ +public class WeexLogInfoFragment extends BaseFragment implements WeexLogInfoPage.PageCloseCallback { + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + WeexLogInfoPage.setCallback(this); + PageIntent intent = new PageIntent(WeexLogInfoPage.class); + intent.mode = PageIntent.MODE_SINGLE_INSTANCE; + FloatPageManager.getInstance().add(intent); + } + + @Override + public void onDestroy() { + super.onDestroy(); + FloatPageManager.getInstance().removeAll(WeexLogInfoPage.class); + } + + @Override + public void onPageDestroy() { + if (getActivity() != null) { + getActivity().finish(); + } + } + +} diff --git a/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/log/WeexLogInfoPage.java b/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/log/WeexLogInfoPage.java new file mode 100644 index 0000000000000000000000000000000000000000..35404da0b340c4cf07f8d5efe319d2046d40fb9a --- /dev/null +++ b/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/log/WeexLogInfoPage.java @@ -0,0 +1,79 @@ +package com.didichuxing.doraemonkit.weex.log; + +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; + +import com.didichuxing.doraemonkit.kit.logInfo.LogInfoFloatPage; +import com.didichuxing.doraemonkit.kit.logInfo.LogLine; +import com.didichuxing.doraemonkit.ui.widget.titlebar.HomeTitleBar; +import com.didichuxing.doraemonkit.weex.R; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author haojianglong + * @date 2019-06-25 + */ +public class WeexLogInfoPage extends LogInfoFloatPage { + + private final String WEEX_TAG = "weex"; + + private static PageCloseCallback mCallback; + + public static void setCallback(PageCloseCallback callback) { + mCallback = callback; + } + + @Override + public void initView() { + super.initView(); + findViewById(R.id.title_bar).setVisibility(View.GONE); + LinearLayout rootView = findViewById(R.id.log_page); + HomeTitleBar homeTitleBar = new HomeTitleBar(getContext()); + homeTitleBar.setBackgroundColor(getResources().getColor(R.color.foreground_wtf)); + homeTitleBar.setTitle(getResources().getString(R.string.dk_console_log_title)); + homeTitleBar.setIcon(R.drawable.dk_close_icon); + homeTitleBar.setListener(new HomeTitleBar.OnTitleBarClickListener() { + @Override + public void onRightClick() { + finish(); + } + }); + LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, + (int) getResources().getDimension(R.dimen.dk_home_title_height)); + rootView.addView(homeTitleBar, 0, params); + } + + @Override + public void onLogCatch(List logLines) { + if (logLines == null || logLines.size() <= 0) { + return; + } + List newLines = new ArrayList<>(); + for (LogLine logLine : logLines) { + if (WEEX_TAG.equals(logLine.getTag())) { + newLines.add(logLine); + } + } + super.onLogCatch(newLines); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + if (mCallback != null) { + mCallback.onPageDestroy(); + mCallback = null; + } + } + + interface PageCloseCallback { + /** + * 页面关闭 + */ + void onPageDestroy(); + } + +} diff --git a/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/log/WeexLogKit.java b/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/log/WeexLogKit.java new file mode 100644 index 0000000000000000000000000000000000000000..2d0daf5e4333076197cd605b436250cbae1c4410 --- /dev/null +++ b/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/log/WeexLogKit.java @@ -0,0 +1,41 @@ +package com.didichuxing.doraemonkit.weex.log; + +import android.content.Context; + +import com.didichuxing.doraemonkit.kit.Category; +import com.didichuxing.doraemonkit.kit.IKit; +import com.didichuxing.doraemonkit.weex.R; +import com.didichuxing.doraemonkit.weex.common.DKCommonActivity; + +/** + * @author haojianglong + * @date 2019-06-11 + */ +public class WeexLogKit implements IKit { + + @Override + public int getCategory() { + return Category.BIZ; + } + + @Override + public int getName() { + return R.string.dk_console_log_name; + } + + @Override + public int getIcon() { + return R.drawable.dk_log_info; + } + + @Override + public void onClick(Context context) { + DKCommonActivity.startWith(context, WeexLogInfoFragment.class); + } + + @Override + public void onAppInit(Context context) { + + } + +} diff --git a/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/storage/StorageAdapter.java b/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/storage/StorageAdapter.java new file mode 100644 index 0000000000000000000000000000000000000000..2aa4e792c9cb69495a36cdd61959480c6ba7fd96 --- /dev/null +++ b/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/storage/StorageAdapter.java @@ -0,0 +1,94 @@ +package com.didichuxing.doraemonkit.weex.storage; + +import android.content.Context; +import android.graphics.Color; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import com.didichuxing.doraemonkit.ui.widget.recyclerview.AbsRecyclerAdapter; +import com.didichuxing.doraemonkit.ui.widget.recyclerview.AbsViewBinder; +import com.didichuxing.doraemonkit.weex.R; + +/** + * @author haojianglong + * @date 2019-06-18 + */ + +public class StorageAdapter extends AbsRecyclerAdapter { + + private OnItemClickListener onItemClickListener; + private final String KEY = "key"; + private final String VALUE = "value"; + + private final int TITLE_BACKGROUND_COLOR = Color.parseColor("#BBBBBB"); + private final int NORMAL_BACKGROUND_COLOR = Color.parseColor("#CDCDCD"); + + public StorageAdapter(Context context) { + super(context); + append(new StorageInfo(KEY, VALUE)); + } + + @Override + protected ViewHolder createViewHolder(View view, int viewType) { + return new ViewHolder(view); + } + + @Override + protected View createView(LayoutInflater inflater, ViewGroup parent, int viewType) { + return inflater.inflate(R.layout.dk_item_storage_watch, parent, false); + } + + public class ViewHolder extends AbsViewBinder { + + private TextView key; + private TextView value; + + public ViewHolder(View view) { + super(view); + } + + @Override + protected void getViews() { + key = getView(R.id.tv_tip_key); + value = getView(R.id.tv_tip_value); + } + + @Override + public void bind(final StorageInfo bean) { + if (getAdapterPosition() == 0) { + key.setBackgroundColor(TITLE_BACKGROUND_COLOR); + value.setBackgroundColor(TITLE_BACKGROUND_COLOR); + } else { + key.setBackgroundColor(NORMAL_BACKGROUND_COLOR); + value.setBackgroundColor(NORMAL_BACKGROUND_COLOR); + } + key.setText(bean.key); + value.setText(bean.value); + getView().setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (getAdapterPosition() != 0 && onItemClickListener != null) { + onItemClickListener.onItemClick(bean); + } + } + }); + } + + } + + public void setOnItemClickListener(OnItemClickListener onItemClickListener) { + this.onItemClickListener = onItemClickListener; + } + + public interface OnItemClickListener { + /** + * 点击事件 + * + * @param info + */ + void onItemClick(StorageInfo info); + } + +} diff --git a/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/storage/StorageDialogFragment.java b/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/storage/StorageDialogFragment.java new file mode 100644 index 0000000000000000000000000000000000000000..747921623b0667dac64c4ddccf10ef6b1741dfd9 --- /dev/null +++ b/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/storage/StorageDialogFragment.java @@ -0,0 +1,53 @@ +package com.didichuxing.doraemonkit.weex.storage; + +import android.app.Dialog; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.DialogFragment; +import android.util.DisplayMetrics; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import com.didichuxing.doraemonkit.weex.R; + + +public class StorageDialogFragment extends DialogFragment { + + public static final String KEY_STORAGE_INFO = "key_storage_info"; + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.dk_item_storage_dialog, container); + return view; + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + if (getArguments() != null) { + StorageInfo info = (StorageInfo) getArguments().getSerializable(KEY_STORAGE_INFO); + if (info != null) { + TextView tv_key = view.findViewById(R.id.tv_name); + TextView tv_value = view.findViewById(R.id.tv_value); + tv_key.setText(info.key); + tv_value.setText(info.value); + } + } + } + + @Override + public void onStart() { + super.onStart(); + Dialog dialog = getDialog(); + if (dialog != null) { + DisplayMetrics dm = new DisplayMetrics(); + getActivity().getWindowManager().getDefaultDisplay().getMetrics(dm); + dialog.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); + } + } + +} diff --git a/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/storage/StorageFragment.java b/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/storage/StorageFragment.java new file mode 100644 index 0000000000000000000000000000000000000000..c379df46cf6634a1bb19fc250343eea55e0cb193 --- /dev/null +++ b/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/storage/StorageFragment.java @@ -0,0 +1,70 @@ +package com.didichuxing.doraemonkit.weex.storage; + +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.View; + +import com.didichuxing.doraemonkit.ui.base.BaseFragment; +import com.didichuxing.doraemonkit.ui.widget.recyclerview.DividerItemDecoration; +import com.didichuxing.doraemonkit.ui.widget.titlebar.HomeTitleBar; +import com.didichuxing.doraemonkit.weex.R; + +import java.util.List; + +/** + * @author haojianglong + * @date 2019-06-18 + */ +public class StorageFragment extends BaseFragment { + + private StorageHacker mStorageHacker; + + @Override + protected int onRequestLayout() { + return R.layout.dk_fragment_storage; + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + initView(); + } + + private void initView() { + mStorageHacker = new StorageHacker(getContext(), true); + + HomeTitleBar titleBar = findViewById(R.id.title_bar); + titleBar.setListener(new HomeTitleBar.OnTitleBarClickListener() { + @Override + public void onRightClick() { + getActivity().finish(); + } + }); + RecyclerView recycler = findViewById(R.id.info_list); + recycler.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false)); + recycler.addItemDecoration(new DividerItemDecoration(DividerItemDecoration.VERTICAL)); + final StorageAdapter storageItemAdapter = new StorageAdapter(getActivity()); + mStorageHacker.fetch(new StorageHacker.OnLoadListener() { + @Override + public void onLoad(List list) { + storageItemAdapter.append(list); + } + }); + + storageItemAdapter.setOnItemClickListener(new StorageAdapter.OnItemClickListener() { + @Override + public void onItemClick(StorageInfo info) { + StorageDialogFragment fragment = new StorageDialogFragment(); + Bundle bundle = new Bundle(); + bundle.putSerializable(StorageDialogFragment.KEY_STORAGE_INFO, info); + fragment.setArguments(bundle); + fragment.show(getFragmentManager(), "dialog"); + } + }); + recycler.setAdapter(storageItemAdapter); + } + +} diff --git a/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/storage/StorageHacker.java b/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/storage/StorageHacker.java new file mode 100644 index 0000000000000000000000000000000000000000..0c78b453781d0ddd917728435efaddfaf7471465 --- /dev/null +++ b/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/storage/StorageHacker.java @@ -0,0 +1,207 @@ +package com.didichuxing.doraemonkit.weex.storage; + +import android.app.Application; +import android.content.Context; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.os.Handler; +import android.os.Looper; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.text.TextUtils; +import android.util.Log; + +import com.taobao.weex.WXSDKEngine; +import com.taobao.weex.appfram.storage.DefaultWXStorage; +import com.taobao.weex.appfram.storage.IWXStorageAdapter; +import com.taobao.weex.appfram.storage.WXSQLiteOpenHelper; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; + +/** + * @author haojianglong + * @date 2019-06-18 + */ + +public final class StorageHacker { + + private IWXStorageAdapter mStorageAdapter; + private Context mContext; + private final boolean isDebug; + + private Handler mHandler = new Handler(Looper.getMainLooper()); + private ExecutorService mExecutor = Executors.newCachedThreadPool(new ThreadFactory() { + @Override + public Thread newThread(@NonNull Runnable r) { + return new Thread(r, "wx_analyzer_storage_dumper"); + } + }); + + public StorageHacker(@NonNull Context context, boolean isDebug) { + mStorageAdapter = WXSDKEngine.getIWXStorageAdapter(); + if (!(context instanceof Application)) { + context = context.getApplicationContext(); + } + this.mContext = context; + this.isDebug = isDebug; + } + + public void destroy() { + if (mHandler != null) { + mHandler.removeCallbacksAndMessages(null); + mHandler = null; + } + + if (mExecutor != null) { + mExecutor.shutdown(); + mExecutor = null; + } + } + + public boolean isDestroy() { + return mHandler == null || mExecutor == null || mExecutor.isShutdown(); + } + + + @SuppressWarnings("unchecked") + public void fetch(@Nullable final OnLoadListener listener) { + if (listener == null) { + return; + } + + if (mStorageAdapter == null) { + listener.onLoad(Collections.emptyList()); + return; + } + + if (!(mStorageAdapter instanceof DefaultWXStorage)) { + listener.onLoad(Collections.emptyList()); + return; + } + + if (isDestroy()) { + listener.onLoad(Collections.emptyList()); + return; + } + + mExecutor.execute(new Runnable() { + @Override + public void run() { + final List resultList = new ArrayList<>(); + WXSQLiteOpenHelper helper = null; + Cursor c = null; + try { + Constructor constructor = WXSQLiteOpenHelper.class.getDeclaredConstructor(Context.class); + constructor.setAccessible(true); + helper = constructor.newInstance(mContext); + + Method method = WXSQLiteOpenHelper.class.getDeclaredMethod("getDatabase"); + method.setAccessible(true); + SQLiteDatabase db = (SQLiteDatabase) method.invoke(helper); + + c = db.query("default_wx_storage", new String[]{"key", "value", "timestamp"}, null, null, null, null, null); + + if (isDebug) { + Log.d("weex-analyzer", "start dump weex storage"); + } + + while (c.moveToNext()) { + StorageInfo info = new StorageInfo(); + info.key = c.getString(c.getColumnIndex("key")); + info.value = c.getString(c.getColumnIndex("value")); + info.timestamp = c.getString(c.getColumnIndex("timestamp")); + if (isDebug) { + Log.d("weex-analyzer", "weex storage[" + info.key + " | " + info.value + "]"); + } + resultList.add(info); + } + + if (isDebug) { + Log.d("weex-analyzer", "end dump weex storage"); + } + + if (mHandler != null) { + mHandler.post(new Runnable() { + @Override + public void run() { + listener.onLoad(resultList); + } + }); + } + + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (c != null) { + c.close(); + } + if (helper != null) { + helper.closeDatabase(); + } + } + } + }); + } + + public void remove(@Nullable final String key, @Nullable final OnRemoveListener listener) { + if (listener == null || TextUtils.isEmpty(key)) { + return; + } + + if (mStorageAdapter == null) { + listener.onRemoved(false); + return; + } + + if (!(mStorageAdapter instanceof DefaultWXStorage)) { + listener.onRemoved(false); + return; + } + + if (isDestroy()) { + listener.onRemoved(false); + return; + } + + mExecutor.execute(new Runnable() { + @Override + public void run() { + try { + DefaultWXStorage storage = (DefaultWXStorage) mStorageAdapter; + Method method = storage.getClass().getDeclaredMethod("performRemoveItem", String.class); + if (method != null) { + method.setAccessible(true); + final boolean result = (boolean) method.invoke(storage, key); + if (mHandler != null) { + mHandler.post(new Runnable() { + @Override + public void run() { + listener.onRemoved(result); + } + }); + method.setAccessible(false); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + } + + interface OnLoadListener { + void onLoad(List list); + } + + interface OnRemoveListener { + void onRemoved(boolean status); + } + +} diff --git a/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/storage/StorageInfo.java b/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/storage/StorageInfo.java new file mode 100644 index 0000000000000000000000000000000000000000..12ad22fb56eae9f4dd1a458b9cd9bb658688104c --- /dev/null +++ b/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/storage/StorageInfo.java @@ -0,0 +1,23 @@ +package com.didichuxing.doraemonkit.weex.storage; + +import java.io.Serializable; + +/** + * @author haojianglong + * @date 2019-06-18 + */ +public class StorageInfo implements Serializable { + + public String key; + public String value; + public String timestamp; + + public StorageInfo() { + } + + public StorageInfo(String key, String value) { + this.key = key; + this.value = value; + } + +} diff --git a/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/storage/StorageKit.java b/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/storage/StorageKit.java new file mode 100644 index 0000000000000000000000000000000000000000..5319c14f82c2c4a8f333a55ee6546f32645748bd --- /dev/null +++ b/Android/doraemonkit_weex/src/main/java/com/didichuxing/doraemonkit/weex/storage/StorageKit.java @@ -0,0 +1,41 @@ +package com.didichuxing.doraemonkit.weex.storage; + +import android.content.Context; + +import com.didichuxing.doraemonkit.kit.Category; +import com.didichuxing.doraemonkit.kit.IKit; +import com.didichuxing.doraemonkit.weex.R; +import com.didichuxing.doraemonkit.weex.common.DKCommonActivity; + +/** + * @author haojianglong + * @date 2019-06-11 + */ +public class StorageKit implements IKit { + + @Override + public int getCategory() { + return Category.BIZ; + } + + @Override + public int getName() { + return R.string.dk_storage_cache_name; + } + + @Override + public int getIcon() { + return R.drawable.dk_file_explorer; + } + + @Override + public void onClick(Context context) { + DKCommonActivity.startWith(context, StorageFragment.class); + } + + @Override + public void onAppInit(Context context) { + + } + +} diff --git a/Android/doraemonkit_weex/src/main/res/layout/dk_fragment_info.xml b/Android/doraemonkit_weex/src/main/res/layout/dk_fragment_info.xml new file mode 100644 index 0000000000000000000000000000000000000000..48739d5868ea0853cc4414bbd48a572cfa26c801 --- /dev/null +++ b/Android/doraemonkit_weex/src/main/res/layout/dk_fragment_info.xml @@ -0,0 +1,24 @@ + + + + + + + + \ No newline at end of file diff --git a/Android/doraemonkit_weex/src/main/res/layout/dk_fragment_info_item.xml b/Android/doraemonkit_weex/src/main/res/layout/dk_fragment_info_item.xml new file mode 100644 index 0000000000000000000000000000000000000000..baa74b404a6a1244dc194e76170ca3f0ba54fa64 --- /dev/null +++ b/Android/doraemonkit_weex/src/main/res/layout/dk_fragment_info_item.xml @@ -0,0 +1,27 @@ + + + + + + + + \ No newline at end of file diff --git a/Android/doraemonkit_weex/src/main/res/layout/dk_fragment_storage.xml b/Android/doraemonkit_weex/src/main/res/layout/dk_fragment_storage.xml new file mode 100644 index 0000000000000000000000000000000000000000..80232b2906d8acab0f674a9ae5f6706144aab557 --- /dev/null +++ b/Android/doraemonkit_weex/src/main/res/layout/dk_fragment_storage.xml @@ -0,0 +1,23 @@ + + + + + + + + \ No newline at end of file diff --git a/Android/doraemonkit_weex/src/main/res/layout/dk_item_storage_dialog.xml b/Android/doraemonkit_weex/src/main/res/layout/dk_item_storage_dialog.xml new file mode 100644 index 0000000000000000000000000000000000000000..06ef52c2d0da7bdd5cf025cfd07e549ce4888de5 --- /dev/null +++ b/Android/doraemonkit_weex/src/main/res/layout/dk_item_storage_dialog.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/Android/doraemonkit_weex/src/main/res/layout/dk_item_storage_watch.xml b/Android/doraemonkit_weex/src/main/res/layout/dk_item_storage_watch.xml new file mode 100644 index 0000000000000000000000000000000000000000..80df4664c933c9b562cdd5ce4e0192157a0a6409 --- /dev/null +++ b/Android/doraemonkit_weex/src/main/res/layout/dk_item_storage_watch.xml @@ -0,0 +1,41 @@ + + + + + + + + + + \ No newline at end of file diff --git a/Android/doraemonkit_weex/src/main/res/values-en-rUS/strings.xml b/Android/doraemonkit_weex/src/main/res/values-en-rUS/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..6f3b2918cccf97c1751b7c2f79525d255207a9f6 --- /dev/null +++ b/Android/doraemonkit_weex/src/main/res/values-en-rUS/strings.xml @@ -0,0 +1,15 @@ + + weexkit + + Log + Weex Logging + Cache + Storage Information + Information + Weex Information + DevTool + Weex DevTool + + key: + value: + diff --git a/Android/doraemonkit_weex/src/main/res/values-zh-rCN/strings.xml b/Android/doraemonkit_weex/src/main/res/values-zh-rCN/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..5ea67f28895d896f7dfc02037057c6ed62ca50d5 --- /dev/null +++ b/Android/doraemonkit_weex/src/main/res/values-zh-rCN/strings.xml @@ -0,0 +1,15 @@ + + weexkit + + 日志 + Weex日志记录 + 缓存 + Storage信息查看 + 信息 + Weex信息查看 + DevTool + Weex DevTool + + key: + value: + diff --git a/Android/doraemonkit_weex/src/main/res/values-zh-rTW/strings.xml b/Android/doraemonkit_weex/src/main/res/values-zh-rTW/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..462fd2dc6b4155aff0ea67fa24dd57328a568a43 --- /dev/null +++ b/Android/doraemonkit_weex/src/main/res/values-zh-rTW/strings.xml @@ -0,0 +1,15 @@ + + weexkit + + 日誌 + Weex日誌記錄 + 緩存 + Storage信息查看 + 信息 + Weex信息查看 + DevTool + Weex DevTool + + key: + value: + diff --git a/Android/doraemonkit_weex/src/main/res/values/strings.xml b/Android/doraemonkit_weex/src/main/res/values/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..5ea67f28895d896f7dfc02037057c6ed62ca50d5 --- /dev/null +++ b/Android/doraemonkit_weex/src/main/res/values/strings.xml @@ -0,0 +1,15 @@ + + weexkit + + 日志 + Weex日志记录 + 缓存 + Storage信息查看 + 信息 + Weex信息查看 + DevTool + Weex DevTool + + key: + value: + diff --git a/Android/doraemonkit_weex/src/main/res/values/styles.xml b/Android/doraemonkit_weex/src/main/res/values/styles.xml new file mode 100644 index 0000000000000000000000000000000000000000..b5eacd5933734381bee2a91a8b81aa4f923ade3d --- /dev/null +++ b/Android/doraemonkit_weex/src/main/res/values/styles.xml @@ -0,0 +1,5 @@ + + +