Skip to content
Browse files

Code Initialization

  • Loading branch information...
1 parent 0822215 commit 742759cde2e2da97bc7ec74c8bfb2487e54afd59 郭阳 committed
Showing with 3,045 additions and 1 deletion.
  1. +1 −0 .gradle/2.8/taskArtifacts/cache.properties
  2. BIN .gradle/2.8/taskArtifacts/cache.properties.lock
  3. BIN .gradle/2.8/taskArtifacts/fileHashes.bin
  4. BIN .gradle/2.8/taskArtifacts/fileSnapshots.bin
  5. BIN .gradle/2.8/taskArtifacts/outputFileStates.bin
  6. BIN .gradle/2.8/taskArtifacts/taskArtifacts.bin
  7. +1 −0 DemoMarsdaemon/.gitignore
  8. +96 −0 DemoMarsdaemon/DemoMarsdaemon.iml
  9. +22 −0 DemoMarsdaemon/build.gradle
  10. +17 −0 DemoMarsdaemon/proguard-rules.pro
  11. +13 −0 DemoMarsdaemon/src/androidTest/java/com/marswin89/marsdaemon/demo/ApplicationTest.java
  12. +28 −0 DemoMarsdaemon/src/main/AndroidManifest.xml
  13. +21 −0 DemoMarsdaemon/src/main/java/com/marswin89/marsdaemon/demo/MainActivity.java
  14. +52 −0 DemoMarsdaemon/src/main/java/com/marswin89/marsdaemon/demo/MyApplication1.java
  15. +51 −0 DemoMarsdaemon/src/main/java/com/marswin89/marsdaemon/demo/MyApplication2.java
  16. +17 −0 DemoMarsdaemon/src/main/java/com/marswin89/marsdaemon/demo/Receiver1.java
  17. +17 −0 DemoMarsdaemon/src/main/java/com/marswin89/marsdaemon/demo/Receiver2.java
  18. +24 −0 DemoMarsdaemon/src/main/java/com/marswin89/marsdaemon/demo/Service1.java
  19. +23 −0 DemoMarsdaemon/src/main/java/com/marswin89/marsdaemon/demo/Service2.java
  20. +19 −0 DemoMarsdaemon/src/main/res/layout/activity_main.xml
  21. BIN DemoMarsdaemon/src/main/res/mipmap-hdpi/ic_launcher.png
  22. BIN DemoMarsdaemon/src/main/res/mipmap-mdpi/ic_launcher.png
  23. BIN DemoMarsdaemon/src/main/res/mipmap-xhdpi/ic_launcher.png
  24. BIN DemoMarsdaemon/src/main/res/mipmap-xxhdpi/ic_launcher.png
  25. BIN DemoMarsdaemon/src/main/res/mipmap-xxxhdpi/ic_launcher.png
  26. +9 −0 DemoMarsdaemon/src/main/res/values-v21/styles.xml
  27. +6 −0 DemoMarsdaemon/src/main/res/values-w820dp/dimens.xml
  28. +6 −0 DemoMarsdaemon/src/main/res/values/colors.xml
  29. +6 −0 DemoMarsdaemon/src/main/res/values/dimens.xml
  30. +4 −0 DemoMarsdaemon/src/main/res/values/strings.xml
  31. +20 −0 DemoMarsdaemon/src/main/res/values/styles.xml
  32. +15 −0 DemoMarsdaemon/src/test/java/com/marswin89/marsdaemon/demo/ExampleUnitTest.java
  33. +1 −0 LibMarsdaemon/.gitignore
  34. +87 −0 LibMarsdaemon/LibMarsdaemon.iml
  35. +30 −0 LibMarsdaemon/build.gradle
  36. +26 −0 LibMarsdaemon/jni/Android.mk
  37. +2 −0 LibMarsdaemon/jni/Application.mk
  38. +21 −0 LibMarsdaemon/jni/com_marswin89_marsdaemon_nativ_NativeDaemonAPI20.h
  39. +21 −0 LibMarsdaemon/jni/com_marswin89_marsdaemon_nativ_NativeDaemonAPI21.h
  40. +92 −0 LibMarsdaemon/jni/common.c
  41. +11 −0 LibMarsdaemon/jni/constant.h
  42. +118 −0 LibMarsdaemon/jni/daemon.c
  43. +145 −0 LibMarsdaemon/jni/daemon_api20.c
  44. +144 −0 LibMarsdaemon/jni/daemon_api21.c
  45. +16 −0 LibMarsdaemon/jni/log.h
  46. BIN LibMarsdaemon/libs/armeabi-v7a/libdaemon_api20.so
  47. BIN LibMarsdaemon/libs/armeabi-v7a/libdaemon_api21.so
  48. BIN LibMarsdaemon/libs/armeabi/libdaemon_api20.so
  49. BIN LibMarsdaemon/libs/armeabi/libdaemon_api21.so
  50. BIN LibMarsdaemon/libs/x86/libdaemon_api20.so
  51. BIN LibMarsdaemon/libs/x86/libdaemon_api21.so
  52. +26 −0 LibMarsdaemon/proguard-rules.pro
  53. +11 −0 LibMarsdaemon/src/main/AndroidManifest.xml
  54. BIN LibMarsdaemon/src/main/assets/armeabi-v7a/daemon
  55. BIN LibMarsdaemon/src/main/assets/armeabi/daemon
  56. BIN LibMarsdaemon/src/main/assets/x86/daemon
  57. +54 −0 LibMarsdaemon/src/main/java/com/marswin89/marsdaemon/DaemonApplication.java
  58. +110 −0 LibMarsdaemon/src/main/java/com/marswin89/marsdaemon/DaemonClient.java
  59. +59 −0 LibMarsdaemon/src/main/java/com/marswin89/marsdaemon/DaemonConfigurations.java
  60. +20 −0 LibMarsdaemon/src/main/java/com/marswin89/marsdaemon/IDaemonClient.java
  61. +97 −0 LibMarsdaemon/src/main/java/com/marswin89/marsdaemon/IDaemonStrategy.java
  62. +28 −0 LibMarsdaemon/src/main/java/com/marswin89/marsdaemon/NativeDaemonBase.java
  63. +35 −0 LibMarsdaemon/src/main/java/com/marswin89/marsdaemon/PackageUtils.java
  64. +28 −0 LibMarsdaemon/src/main/java/com/marswin89/marsdaemon/nativ/NativeDaemonAPI20.java
  65. +27 −0 LibMarsdaemon/src/main/java/com/marswin89/marsdaemon/nativ/NativeDaemonAPI21.java
  66. +144 −0 LibMarsdaemon/src/main/java/com/marswin89/marsdaemon/strategy/DaemonStrategy21.java
  67. +204 −0 LibMarsdaemon/src/main/java/com/marswin89/marsdaemon/strategy/DaemonStrategy22.java
  68. +218 −0 LibMarsdaemon/src/main/java/com/marswin89/marsdaemon/strategy/DaemonStrategy23.java
  69. +143 −0 LibMarsdaemon/src/main/java/com/marswin89/marsdaemon/strategy/DaemonStrategyUnder21.java
  70. +215 −0 LibMarsdaemon/src/main/java/com/marswin89/marsdaemon/strategy/DaemonStrategyXiaomi.java
  71. +3 −0 LibMarsdaemon/src/main/res/values/strings.xml
  72. +15 −0 LibMarsdaemon/src/test/java/com/marswin89/marsdaemon/ExampleUnitTest.java
  73. +19 −0 Marsdaemon2.iml
  74. +87 −1 README.md
  75. +23 −0 build.gradle
  76. +12 −0 build/intermediates/dex-cache/cache.xml
  77. +18 −0 gradle.properties
  78. BIN gradle/wrapper/gradle-wrapper.jar
  79. +6 −0 gradle/wrapper/gradle-wrapper.properties
  80. +160 −0 gradlew
  81. +90 −0 gradlew.bat
  82. +10 −0 local.properties
  83. +1 −0 settings.gradle
View
1 .gradle/2.8/taskArtifacts/cache.properties
@@ -0,0 +1 @@
+#Thu Dec 24 18:13:42 CST 2015
View
BIN .gradle/2.8/taskArtifacts/cache.properties.lock
Binary file not shown.
View
BIN .gradle/2.8/taskArtifacts/fileHashes.bin
Binary file not shown.
View
BIN .gradle/2.8/taskArtifacts/fileSnapshots.bin
Binary file not shown.
View
BIN .gradle/2.8/taskArtifacts/outputFileStates.bin
Binary file not shown.
View
BIN .gradle/2.8/taskArtifacts/taskArtifacts.bin
Binary file not shown.
View
1 DemoMarsdaemon/.gitignore
@@ -0,0 +1 @@
+/build
View
96 DemoMarsdaemon/DemoMarsdaemon.iml
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module external.linked.project.id=":DemoMarsdaemon" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="Marsdaemon2" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
+ <component name="FacetManager">
+ <facet type="android-gradle" name="Android-Gradle">
+ <configuration>
+ <option name="GRADLE_PROJECT_PATH" value=":DemoMarsdaemon" />
+ </configuration>
+ </facet>
+ <facet type="android" name="Android">
+ <configuration>
+ <option name="SELECTED_BUILD_VARIANT" value="debug" />
+ <option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
+ <option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
+ <option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
+ <option name="ASSEMBLE_TEST_TASK_NAME" value="assembleDebugAndroidTest" />
+ <option name="COMPILE_JAVA_TEST_TASK_NAME" value="compileDebugAndroidTestSources" />
+ <afterSyncTasks>
+ <task>generateDebugAndroidTestSources</task>
+ <task>generateDebugSources</task>
+ </afterSyncTasks>
+ <option name="ALLOW_USER_CONFIGURATION" value="false" />
+ <option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
+ <option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
+ <option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/src/main/res" />
+ <option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
+ </configuration>
+ </facet>
+ </component>
+ <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false">
+ <output url="file://$MODULE_DIR$/build/intermediates/classes/debug" />
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/debug" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/androidTest/debug" isTestSource="true" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/androidTest/debug" isTestSource="true" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/debug" isTestSource="true" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" type="java-test-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/androidTest/debug" type="java-test-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/assets" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/blame" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/debug" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/appcompat-v7/23.1.1/jars" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/design/23.1.1/jars" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/recyclerview-v7/23.1.1/jars" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-v4/23.1.1/jars" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/restart-dex" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/tmp" />
+ <excludeFolder url="file://$MODULE_DIR$/build/outputs" />
+ <excludeFolder url="file://$MODULE_DIR$/build/tmp" />
+ </content>
+ <orderEntry type="jdk" jdkName="Android API 23 Platform" jdkType="Android SDK" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="library" exported="" name="recyclerview-v7-23.1.1" level="project" />
+ <orderEntry type="library" exported="" name="support-annotations-23.1.1" level="project" />
+ <orderEntry type="library" exported="" name="support-v4-23.1.1" level="project" />
+ <orderEntry type="library" exported="" name="design-23.1.1" level="project" />
+ <orderEntry type="library" exported="" name="appcompat-v7-23.1.1" level="project" />
+ <orderEntry type="module" module-name="LibMarsdaemon" exported="" />
+ </component>
+</module>
View
22 DemoMarsdaemon/build.gradle
@@ -0,0 +1,22 @@
+apply plugin: 'com.android.application'
+
+android {
+ compileSdkVersion 23
+ buildToolsVersion "23.0.2"
+
+ defaultConfig {
+ applicationId "com.marswin89.marsdaemon.demo"
+ minSdkVersion 10
+ targetSdkVersion 23
+ versionCode 1
+ versionName "1.0"
+ }
+}
+
+dependencies {
+ compile fileTree(dir: 'libs', include: ['*.jar'])
+ testCompile 'junit:junit:4.12'
+ compile 'com.android.support:appcompat-v7:23.1.1'
+ compile 'com.android.support:design:23.1.1'
+ compile project(':LibMarsdaemon')
+}
View
17 DemoMarsdaemon/proguard-rules.pro
@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /Users/guoyang/Developer/android-sdk-macosx/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
View
13 DemoMarsdaemon/src/androidTest/java/com/marswin89/marsdaemon/demo/ApplicationTest.java
@@ -0,0 +1,13 @@
+package com.marswin89.marsdaemon.demo;
+
+import android.app.Application;
+import android.test.ApplicationTestCase;
+
+/**
+ * <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
+ */
+public class ApplicationTest extends ApplicationTestCase<Application> {
+ public ApplicationTest() {
+ super(Application.class);
+ }
+}
View
28 DemoMarsdaemon/src/main/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.marswin89.marsdaemon.demo">
+
+ <application
+ android:name=".MyApplication1"
+ android:allowBackup="true"
+ android:icon="@mipmap/ic_launcher"
+ android:label="@string/app_name"
+ android:supportsRtl="true"
+ android:theme="@style/AppTheme">
+ <activity
+ android:name="com.marswin89.marsdaemon.demo.MainActivity"
+ android:label="@string/app_name"
+ android:theme="@android:style/Theme.NoTitleBar">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ <service android:name=".Service1" android:process=":process1"/>
+ <receiver android:name=".Receiver1" android:process=":process1"/>
+ <service android:name=".Service2" android:process=":process2"/>
+ <receiver android:name=".Receiver2" android:process=":process2"/>
+ </application>
+
+</manifest>
View
21 DemoMarsdaemon/src/main/java/com/marswin89/marsdaemon/demo/MainActivity.java
@@ -0,0 +1,21 @@
+package com.marswin89.marsdaemon.demo;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+
+/**
+ *
+ * Created by Mars on 12/24/15.
+ */
+public class MainActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+
+ //you have to start the service once.
+ startService(new Intent(MainActivity.this, Service1.class));
+ }
+}
View
52 DemoMarsdaemon/src/main/java/com/marswin89/marsdaemon/demo/MyApplication1.java
@@ -0,0 +1,52 @@
+package com.marswin89.marsdaemon.demo;
+
+import android.content.Context;
+
+import com.marswin89.marsdaemon.DaemonApplication;
+import com.marswin89.marsdaemon.DaemonConfigurations;
+
+/**
+ * Implementation 1<br/>
+ * override one method is ok.<br/>
+ *
+ * Created by Mars on 12/24/15.
+ */
+public class MyApplication1 extends DaemonApplication {
+ /**
+ * you can override this method instead of {@link android.app.Application attachBaseContext}
+ * @param base
+ */
+ @Override
+ public void attachBaseContextByDaemon(Context base) {
+ super.attachBaseContextByDaemon(base);
+ }
+
+
+ /**
+ * give the configuration to lib in this callback
+ * @return
+ */
+ @Override
+ protected DaemonConfigurations getDaemonConfigurations() {
+ DaemonConfigurations.DaemonConfiguration configuration1 = new DaemonConfigurations.DaemonConfiguration("com.marswin89.marsdaemon.demo:process1", Service1.class.getCanonicalName(), Receiver1.class.getCanonicalName());
+ DaemonConfigurations.DaemonConfiguration configuration2 = new DaemonConfigurations.DaemonConfiguration("com.marswin89.marsdaemon.demo:process2", Service2.class.getCanonicalName(), Receiver2.class.getCanonicalName());
+ DaemonConfigurations.DaemonListener listener = new MyDaemonListener();
+ //return new DaemonConfigurations(configuration1, configuration2);//listener can be null
+ return new DaemonConfigurations(configuration1, configuration2, listener);
+ }
+
+
+ class MyDaemonListener implements DaemonConfigurations.DaemonListener{
+ @Override
+ public void onPersistentStart(Context context) {
+ }
+
+ @Override
+ public void onDaemonAssistantStart(Context context) {
+ }
+
+ @Override
+ public void onWatchDaemonDaed() {
+ }
+ }
+}
View
51 DemoMarsdaemon/src/main/java/com/marswin89/marsdaemon/demo/MyApplication2.java
@@ -0,0 +1,51 @@
+package com.marswin89.marsdaemon.demo;
+
+import android.app.Application;
+import android.content.Context;
+
+import com.marswin89.marsdaemon.DaemonApplication;
+import com.marswin89.marsdaemon.DaemonClient;
+import com.marswin89.marsdaemon.DaemonConfigurations;
+
+/**
+ * Implementation 2<br/>
+ * if you have to extends other Application, use this method.<br/>
+ *
+ * Created by Mars on 12/24/15.
+ */
+public class MyApplication2 extends Application {
+
+ private DaemonClient mDaemonClient;
+
+ @Override
+ protected void attachBaseContext(Context base) {
+ super.attachBaseContext(base);
+ mDaemonClient = new DaemonClient(createDaemonConfigurations());
+ mDaemonClient.onAttachBaseContext(base);
+ }
+
+
+
+ private DaemonConfigurations createDaemonConfigurations(){
+ DaemonConfigurations.DaemonConfiguration configuration1 = new DaemonConfigurations.DaemonConfiguration("com.marswin89.marsdaemon.demo:process1", Service1.class.getCanonicalName(), Receiver1.class.getCanonicalName());
+ DaemonConfigurations.DaemonConfiguration configuration2 = new DaemonConfigurations.DaemonConfiguration("com.marswin89.marsdaemon.demo:process2", Service2.class.getCanonicalName(), Receiver2.class.getCanonicalName());
+ DaemonConfigurations.DaemonListener listener = new MyDaemonListener();
+ //return new DaemonConfigurations(configuration1, configuration2);//listener can be null
+ return new DaemonConfigurations(configuration1, configuration2, listener);
+ }
+
+
+ class MyDaemonListener implements DaemonConfigurations.DaemonListener{
+ @Override
+ public void onPersistentStart(Context context) {
+ }
+
+ @Override
+ public void onDaemonAssistantStart(Context context) {
+ }
+
+ @Override
+ public void onWatchDaemonDaed() {
+ }
+ }
+}
View
17 DemoMarsdaemon/src/main/java/com/marswin89/marsdaemon/demo/Receiver1.java
@@ -0,0 +1,17 @@
+package com.marswin89.marsdaemon.demo;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+/**
+ * DO NOT do anything in this Receiver!<br/>
+ *
+ * Created by Mars on 12/24/15.
+ */
+public class Receiver1 extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+
+ }
+}
View
17 DemoMarsdaemon/src/main/java/com/marswin89/marsdaemon/demo/Receiver2.java
@@ -0,0 +1,17 @@
+package com.marswin89.marsdaemon.demo;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+/**
+ * DO NOT do anything in this Receiver!<br/>
+ *
+ * Created by Mars on 12/24/15.
+ */
+public class Receiver2 extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+
+ }
+}
View
24 DemoMarsdaemon/src/main/java/com/marswin89/marsdaemon/demo/Service1.java
@@ -0,0 +1,24 @@
+package com.marswin89.marsdaemon.demo;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+
+/**
+ * This Service is Persistent Service. Do some what you want to do here.<br/>
+ *
+ * Created by Mars on 12/24/15.
+ */
+public class Service1 extends Service{
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ //TODO do some thing what you want..
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+}
View
23 DemoMarsdaemon/src/main/java/com/marswin89/marsdaemon/demo/Service2.java
@@ -0,0 +1,23 @@
+package com.marswin89.marsdaemon.demo;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+
+/**
+ * DO NOT do anything in this Service!<br/>
+ *
+ * Created by Mars on 12/24/15.
+ */
+public class Service2 extends Service{
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ return Service.START_NOT_STICKY;
+ }
+}
View
19 DemoMarsdaemon/src/main/res/layout/activity_main.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:fitsSystemWindows="true"
+ android:background="@android:color/black"
+ tools:context="com.marswin89.marsdaemon.demo.MainActivity">
+
+ <TextView
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:textSize="30sp"
+ android:text="@string/hello"
+ android:layout_centerInParent="true"
+ android:textColor="@android:color/white"
+ />
+
+</RelativeLayout>
View
BIN DemoMarsdaemon/src/main/res/mipmap-hdpi/ic_launcher.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN DemoMarsdaemon/src/main/res/mipmap-mdpi/ic_launcher.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN DemoMarsdaemon/src/main/res/mipmap-xhdpi/ic_launcher.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN DemoMarsdaemon/src/main/res/mipmap-xxhdpi/ic_launcher.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN DemoMarsdaemon/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
9 DemoMarsdaemon/src/main/res/values-v21/styles.xml
@@ -0,0 +1,9 @@
+<resources>
+
+ <style name="AppTheme.NoActionBar">
+ <item name="windowActionBar">false</item>
+ <item name="windowNoTitle">true</item>
+ <item name="android:windowDrawsSystemBarBackgrounds">true</item>
+ <item name="android:statusBarColor">@android:color/transparent</item>
+ </style>
+</resources>
View
6 DemoMarsdaemon/src/main/res/values-w820dp/dimens.xml
@@ -0,0 +1,6 @@
+<resources>
+ <!-- Example customization of dimensions originally defined in res/values/dimens.xml
+ (such as screen margins) for screens with more than 820dp of available width. This
+ would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
+ <dimen name="activity_horizontal_margin">64dp</dimen>
+</resources>
View
6 DemoMarsdaemon/src/main/res/values/colors.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <color name="colorPrimary">#3F51B5</color>
+ <color name="colorPrimaryDark">#303F9F</color>
+ <color name="colorAccent">#FF4081</color>
+</resources>
View
6 DemoMarsdaemon/src/main/res/values/dimens.xml
@@ -0,0 +1,6 @@
+<resources>
+ <!-- Default screen margins, per the Android Design guidelines. -->
+ <dimen name="activity_horizontal_margin">16dp</dimen>
+ <dimen name="activity_vertical_margin">16dp</dimen>
+ <dimen name="fab_margin">16dp</dimen>
+</resources>
View
4 DemoMarsdaemon/src/main/res/values/strings.xml
@@ -0,0 +1,4 @@
+<resources>
+ <string name="hello">Hello, this is Mars.</string>
+ <string name="app_name">MarsDaemon</string>
+</resources>
View
20 DemoMarsdaemon/src/main/res/values/styles.xml
@@ -0,0 +1,20 @@
+<resources>
+
+ <!-- Base application theme. -->
+ <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
+ <!-- Customize your theme here. -->
+ <item name="colorPrimary">@color/colorPrimary</item>
+ <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
+ <item name="colorAccent">@color/colorAccent</item>
+ </style>
+
+ <style name="AppTheme.NoActionBar">
+ <item name="windowActionBar">false</item>
+ <item name="windowNoTitle">true</item>
+ </style>
+
+ <style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
+
+ <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
+
+</resources>
View
15 DemoMarsdaemon/src/test/java/com/marswin89/marsdaemon/demo/ExampleUnitTest.java
@@ -0,0 +1,15 @@
+package com.marswin89.marsdaemon.demo;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * To work on unit tests, switch the Test Artifact in the Build Variants view.
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() throws Exception {
+ assertEquals(4, 2 + 2);
+ }
+}
View
1 LibMarsdaemon/.gitignore
@@ -0,0 +1 @@
+/build
View
87 LibMarsdaemon/LibMarsdaemon.iml
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module external.linked.project.id=":LibMarsdaemon" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="Marsdaemon2" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
+ <component name="FacetManager">
+ <facet type="android-gradle" name="Android-Gradle">
+ <configuration>
+ <option name="GRADLE_PROJECT_PATH" value=":LibMarsdaemon" />
+ </configuration>
+ </facet>
+ <facet type="android" name="Android">
+ <configuration>
+ <option name="SELECTED_BUILD_VARIANT" value="debug" />
+ <option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
+ <option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
+ <option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
+ <option name="ASSEMBLE_TEST_TASK_NAME" value="assembleDebugAndroidTest" />
+ <option name="COMPILE_JAVA_TEST_TASK_NAME" value="compileDebugAndroidTestSources" />
+ <afterSyncTasks>
+ <task>generateDebugAndroidTestSources</task>
+ <task>generateDebugSources</task>
+ </afterSyncTasks>
+ <option name="ALLOW_USER_CONFIGURATION" value="false" />
+ <option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
+ <option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
+ <option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/src/main/res" />
+ <option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
+ <option name="LIBRARY_PROJECT" value="true" />
+ </configuration>
+ </facet>
+ </component>
+ <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false">
+ <output url="file://$MODULE_DIR$/build/intermediates/classes/debug" />
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/debug" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/androidTest/debug" isTestSource="true" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/androidTest/debug" isTestSource="true" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/debug" isTestSource="true" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" type="java-test-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/androidTest/debug" type="java-test-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/assets" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/annotations" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/bundles" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/lint" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/proguard-rules" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
+ <excludeFolder url="file://$MODULE_DIR$/build/outputs" />
+ <excludeFolder url="file://$MODULE_DIR$/build/tmp" />
+ </content>
+ <orderEntry type="jdk" jdkName="Android API 23 Platform" jdkType="Android SDK" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="library" exported="" name="support-annotations-23.1.1" level="project" />
+ <orderEntry type="library" exported="" name="support-v4-23.1.1" level="project" />
+ <orderEntry type="library" exported="" name="appcompat-v7-23.1.1" level="project" />
+ </component>
+</module>
View
30 LibMarsdaemon/build.gradle
@@ -0,0 +1,30 @@
+apply plugin: 'com.android.library'
+
+android {
+ compileSdkVersion 23
+ buildToolsVersion "23.0.2"
+
+ defaultConfig {
+ minSdkVersion 10
+ targetSdkVersion 23
+ versionCode 1
+ versionName "1.0"
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+ sourceSets {
+ main {
+ jniLibs.srcDirs =['libs']
+ }
+ }
+}
+
+dependencies {
+ compile fileTree(dir: 'libs', include: ['*.jar'])
+ testCompile 'junit:junit:4.12'
+ compile 'com.android.support:appcompat-v7:23.1.1'
+}
View
26 LibMarsdaemon/jni/Android.mk
@@ -0,0 +1,26 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+LOCAL_MODULE := daemon_api20
+LOCAL_SRC_FILES := daemon_api20.c \
+ common.c
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
+LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog -lm -lz
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := daemon_api21
+LOCAL_SRC_FILES := daemon_api21.c \
+ common.c
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
+LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog -lm -lz
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := daemon
+LOCAL_SRC_FILES := daemon.c
+LOCAL_CFLAGS += -pie -fPIE
+LOCAL_LDFLAGS += -pie -fPIE
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
+LOCAL_LDLIBS += -L$(SYSROOT)/usr/lib -llog -lm -lz
+include $(BUILD_EXECUTABLE)
+
View
2 LibMarsdaemon/jni/Application.mk
@@ -0,0 +1,2 @@
+APP_ABI := armeabi armeabi-v7a x86
+APP_PLATFORM := android-15
View
21 LibMarsdaemon/jni/com_marswin89_marsdaemon_nativ_NativeDaemonAPI20.h
@@ -0,0 +1,21 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_marswin89_marsdaemon_nativ_NativeDaemonAPI20 */
+
+#ifndef _Included_com_marswin89_marsdaemon_nativ_NativeDaemonAPI20
+#define _Included_com_marswin89_marsdaemon_nativ_NativeDaemonAPI20
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: com_marswin89_marsdaemon_nativ_NativeDaemonAPI20
+ * Method: doDaemon
+ * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_com_marswin89_marsdaemon_nativ_NativeDaemonAPI20_doDaemon
+ (JNIEnv *, jobject, jstring, jstring, jstring);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
View
21 LibMarsdaemon/jni/com_marswin89_marsdaemon_nativ_NativeDaemonAPI21.h
@@ -0,0 +1,21 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_marswin89_marsdaemon_nativ_NativeDaemonAPI21 */
+
+#ifndef _Included_com_marswin89_marsdaemon_nativ_NativeDaemonAPI21
+#define _Included_com_marswin89_marsdaemon_nativ_NativeDaemonAPI21
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: com_marswin89_marsdaemon_nativ_NativeDaemonAPI21
+ * Method: doDaemon
+ * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_com_marswin89_marsdaemon_nativ_NativeDaemonAPI21_doDaemon
+ (JNIEnv *, jobject, jstring, jstring, jstring, jstring);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
View
92 LibMarsdaemon/jni/common.c
@@ -0,0 +1,92 @@
+/*
+ * File : daemon_api21.c
+ * Author : Mars Kwok
+ * Date : Jul. 21, 2015
+ * Description : common method here
+ *
+ * Copyright (C) Mars Kwok<Marswin89@gmail.com>
+ *
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/inotify.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#include "log.h"
+
+/**
+ * get the android version code
+ */
+int get_version(){
+ char value[8] = "";
+ __system_property_get("ro.build.version.sdk", value);
+ return atoi(value);
+}
+
+/**
+ * stitch three string to one
+ */
+char *str_stitching(const char *str1, const char *str2, const char *str3){
+ char *result;
+ result = (char*) malloc(strlen(str1) + strlen(str2) + strlen(str3) + 1);
+ if (!result){
+ return NULL;
+ }
+ strcpy(result, str1);
+ strcat(result, str2);
+ strcat(result, str3);
+ return result;
+}
+
+/**
+ * get android context
+ */
+jobject get_context(JNIEnv* env, jobject jobj){
+ jclass thiz_cls = (*env)->GetObjectClass(env, jobj);
+ jfieldID context_field = (*env)->GetFieldID(env, thiz_cls, "mContext", "Landroid/content/Context;");
+ return (*env)->GetObjectField(env, jobj, context_field);
+}
+
+
+char* get_package_name(JNIEnv* env, jobject jobj){
+ jobject context_obj = get_context(env, jobj);
+ jclass context_cls = (*env)->GetObjectClass(env, context_obj);
+ jmethodID getpackagename_method = (*env)->GetMethodID(jobj, context_cls, "getPackageName", "()Ljava/lang/String;");
+ jstring package_name = (jstring)(*env)->CallObjectMethod(env, context_obj, getpackagename_method);
+ return (char*)(*env)->GetStringUTFChars(env, package_name, 0);
+}
+
+
+/**
+ * call java callback
+ */
+void java_callback(JNIEnv* env, jobject jobj, char* method_name){
+ jclass cls = (*env)->GetObjectClass(env, jobj);
+ jmethodID cb_method = (*env)->GetMethodID(env, cls, method_name, "()V");
+ (*env)->CallVoidMethod(env, jobj, cb_method);
+}
+
+/**
+ * start a android service
+ */
+void start_service(char* package_name, char* service_name){
+ pid_t pid = fork();
+ if(pid < 0){
+ //error, do nothing...
+ }else if(pid == 0){
+ if(package_name == NULL || service_name == NULL){
+ exit(EXIT_SUCCESS);
+ }
+ int version = get_version();
+ char* pkg_svc_name = str_stitching(package_name, "/", service_name);
+ if (version >= 17 || version == 0) {
+ execlp("am", "am", "startservice", "--user", "0", "-n", pkg_svc_name, (char *) NULL);
+ } else {
+ execlp("am", "am", "startservice", "-n", pkg_svc_name, (char *) NULL);
+ }
+ exit(EXIT_SUCCESS);
+ }else{
+ waitpid(pid, NULL, 0);
+ }
+}
View
11 LibMarsdaemon/jni/constant.h
@@ -0,0 +1,11 @@
+#define NATIVE_DAEMON_NAME "mars_d"
+#define BUFFER_SIZE 2048
+#define DAEMON_CALLBACK_NAME "onDaemonDead"
+#define PARAM_PIPE_1_READ "-p1r"
+#define PARAM_PIPE_1_WRITE "-p1w"
+#define PARAM_PIPE_2_READ "-p2r"
+#define PARAM_PIPE_2_WRITE "-p2w"
+#define PARAM_PKG_NAME "-p"
+#define PARAM_SVC_NAME "-s"
+
+
View
118 LibMarsdaemon/jni/daemon.c
@@ -0,0 +1,118 @@
+/*
+ * File : daemon_api21.c
+ * Author : Mars Kwok
+ * Date : Jul. 21, 2015
+ * Description : This is native process to watch parent process.
+ *
+ * Copyright (C) Mars Kwok<Marswin89@gmail.com>
+ *
+ */
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "log.h"
+#include "constant.h"
+
+
+/**
+ * get the android version code
+ */
+int get_version(){
+ char value[8] = "";
+ __system_property_get("ro.build.version.sdk", value);
+ return atoi(value);
+}
+
+char *str_stitching(const char *str1, const char *str2, const char *str3){
+ char *result;
+ result = (char*) malloc(strlen(str1) + strlen(str2) + strlen(str3) + 1);
+ if (!result){
+ return NULL;
+ }
+ strcpy(result, str1);
+ strcat(result, str2);
+ strcat(result, str3);
+ return result;
+}
+
+/**
+ * start a android service
+ */
+void start_service(char* package_name, char* service_name){
+ pid_t pid = fork();
+ if(pid < 0){
+ //error, do nothing...
+ }else if(pid == 0){
+ if(package_name == NULL || service_name == NULL){
+ exit(EXIT_SUCCESS);
+ }
+ int version = get_version();
+ char* pkg_svc_name = str_stitching(package_name, "/", service_name);
+ if (version >= 17 || version == 0) {
+ execlp("am", "am", "startservice", "--user", "0", "-n", pkg_svc_name, (char *) NULL);
+ } else {
+ execlp("am", "am", "startservice", "-n", pkg_svc_name, (char *) NULL);
+ }
+ exit(EXIT_SUCCESS);
+ }else{
+ waitpid(pid, NULL, 0);
+ }
+}
+
+
+
+int main(int argc, char *argv[]){
+ pid_t pid = fork();
+ if(pid == 0){
+ setsid();
+ int pipe_fd1[2];
+ int pipe_fd2[2];
+ char* pkg_name;
+ char* svc_name;
+ if(argc < 13){
+ LOGE("daemon parameters error");
+ return ;
+ }
+ int i;
+ for (i = 0; i < argc; i ++){
+ if(argv[i] == NULL){
+ continue;
+ }
+ if (!strcmp(PARAM_PKG_NAME, argv[i])){
+ pkg_name = argv[i + 1];
+ }else if (!strcmp(PARAM_SVC_NAME, argv[i])) {
+ svc_name = argv[i + 1];
+ }else if (!strcmp(PARAM_PIPE_1_READ, argv[i])){
+ char* p1r = argv[i + 1];
+ pipe_fd1[0] = atoi(p1r);
+ }else if (!strcmp(PARAM_PIPE_1_WRITE, argv[i])) {
+ char* p1w = argv[i + 1];
+ pipe_fd1[1] = atoi(p1w);
+ }else if (!strcmp(PARAM_PIPE_2_READ, argv[i])) {
+ char* p2r = argv[i + 1];
+ pipe_fd2[0] = atoi(p2r);
+ }else if (!strcmp(PARAM_PIPE_2_WRITE, argv[i])) {
+ char* p2w = argv[i + 1];
+ pipe_fd2[1] = atoi(p2w);
+ }
+ }
+
+ close(pipe_fd1[0]);
+ close(pipe_fd2[1]);
+
+ char r_buf[100];
+ int r_num;
+ memset(r_buf,0, sizeof(r_buf));
+
+ r_num=read(pipe_fd2[0], r_buf, 100);
+ LOGE("Watch >>>>PARENT<<<< Dead !!");
+ int count = 0;
+ while(count < 50){
+ start_service(pkg_name, svc_name);
+ usleep(100000);
+ count++;
+ }
+ }else{
+ exit(EXIT_SUCCESS);
+ }
+}
View
145 LibMarsdaemon/jni/daemon_api20.c
@@ -0,0 +1,145 @@
+/*
+ * File : daemon_api21.c
+ * Author : Mars Kwok
+ * Date : Jul. 21, 2015
+ * Description : This is used to watch process dead under api 20
+ *
+ * Copyright (C) Mars Kwok<Marswin89@gmail.com>
+ *
+ */
+#include <stdio.h>
+#include <dirent.h>
+#include <unistd.h>
+
+#include "log.h"
+#include "constant.h"
+#include "com_marswin89_marsdaemon_nativ_NativeDaemonAPI20.h"
+
+
+
+/**
+ * get the process pid by process name
+ */
+int find_pid_by_name(char *pid_name, int *pid_list){
+ DIR *dir;
+ struct dirent *next;
+ int i = 0;
+ pid_list[0] = 0;
+ dir = opendir("/proc");
+ if (!dir){
+ return 0;
+ }
+ while ((next = readdir(dir)) != NULL){
+ FILE *status;
+ char proc_file_name[BUFFER_SIZE];
+ char buffer[BUFFER_SIZE];
+ char process_name[BUFFER_SIZE];
+
+ if (strcmp(next->d_name, "..") == 0){
+ continue;
+ }
+ if (!isdigit(*next->d_name)){
+ continue;
+ }
+ sprintf(proc_file_name, "/proc/%s/cmdline", next->d_name);
+ if (!(status = fopen(proc_file_name, "r"))){
+ continue;
+ }
+ if (fgets(buffer, BUFFER_SIZE - 1, status) == NULL){
+ fclose(status);
+ continue;
+ }
+ fclose(status);
+ sscanf(buffer, "%[^-]", process_name);
+ if (strcmp(process_name, pid_name) == 0){
+ pid_list[i ++] = atoi(next->d_name);
+ }
+ }
+ if (pid_list){
+ pid_list[i] = 0;
+ }
+ closedir(dir);
+ return i;
+}
+
+/**
+ * kill all process by name
+ */
+void kill_zombie_process(char* zombie_name){
+ int pid_list[200];
+ int total_num = find_pid_by_name(zombie_name, pid_list);
+ LOGD("zombie process name is %s, and number is %d, killing...", zombie_name, total_num);
+ int i;
+ for (i = 0; i < total_num; i ++) {
+ int retval = 0;
+ int daemon_pid = pid_list[i];
+ if (daemon_pid > 1 && daemon_pid != getpid() && daemon_pid != getppid()){
+ retval = kill(daemon_pid, SIGTERM);
+ if (!retval){
+ LOGD("kill zombie successfully, zombie`s pid = %d", daemon_pid);
+ }else{
+ LOGE("kill zombie failed, zombie`s pid = %d", daemon_pid);
+ }
+ }
+ }
+}
+
+JNIEXPORT void JNICALL Java_com_marswin89_marsdaemon_nativ_NativeDaemonAPI20_doDaemon(JNIEnv *env, jobject jobj, jstring pkgName, jstring svcName, jstring daemonPath){
+ if(pkgName == NULL || svcName == NULL || daemonPath == NULL){
+ LOGE("native doDaemon parameters cannot be NULL !");
+ return ;
+ }
+
+ char *pkg_name = (char*)(*env)->GetStringUTFChars(env, pkgName, 0);
+ char *svc_name = (char*)(*env)->GetStringUTFChars(env, svcName, 0);
+ char *daemon_path = (char*)(*env)->GetStringUTFChars(env, daemonPath, 0);
+
+ kill_zombie_process(NATIVE_DAEMON_NAME);
+
+ int pipe_fd1[2];//order to watch child
+ int pipe_fd2[2];//order to watch parent
+
+ pid_t pid;
+ char r_buf[100];
+ int r_num;
+ memset(r_buf, 0, sizeof(r_buf));
+ if(pipe(pipe_fd1)<0){
+ LOGE("pipe1 create error");
+ return ;
+ }
+ if(pipe(pipe_fd2)<0){
+ LOGE("pipe2 create error");
+ return ;
+ }
+
+ char str_p1r[10];
+ char str_p1w[10];
+ char str_p2r[10];
+ char str_p2w[10];
+
+ sprintf(str_p1r,"%d",pipe_fd1[0]);
+ sprintf(str_p1w,"%d",pipe_fd1[1]);
+ sprintf(str_p2r,"%d",pipe_fd2[0]);
+ sprintf(str_p2w,"%d",pipe_fd2[1]);
+
+
+ if((pid=fork())==0){
+ execlp(daemon_path,
+ NATIVE_DAEMON_NAME,
+ PARAM_PKG_NAME, pkg_name,
+ PARAM_SVC_NAME, svc_name,
+ PARAM_PIPE_1_READ, str_p1r,
+ PARAM_PIPE_1_WRITE, str_p1w,
+ PARAM_PIPE_2_READ, str_p2r,
+ PARAM_PIPE_2_WRITE, str_p2w,
+ (char *) NULL);
+ }else if(pid>0){
+ close(pipe_fd1[1]);
+ close(pipe_fd2[0]);
+ //wait for child
+ r_num=read(pipe_fd1[0], r_buf, 100);
+ LOGE("Watch >>>>CHILD<<<< Dead !!!");
+ java_callback(env, jobj, DAEMON_CALLBACK_NAME);
+ }
+}
+
View
144 LibMarsdaemon/jni/daemon_api21.c
@@ -0,0 +1,144 @@
+/*
+ * File : daemon_api21.c
+ * Author : Mars Kwok
+ * Date : Jul. 21, 2015
+ * Description : This is used to watch process dead over api 21
+ *
+ * Copyright (C) Mars Kwok<Marswin89@gmail.com>
+ *
+ */
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/inotify.h>
+
+#include "com_marswin89_marsdaemon_nativ_NativeDaemonAPI21.h"
+#include "log.h"
+#include "constant.h"
+
+void waitfor_self_observer(char* observer_file_path){
+ int lockFileDescriptor = open(observer_file_path, O_RDONLY);
+ if (lockFileDescriptor == -1){
+ LOGE("Watched >>>>OBSERVER<<<< has been ready before watching...");
+ return ;
+ }
+
+ void *p_buf = malloc(sizeof(struct inotify_event));
+ if (p_buf == NULL){
+ LOGE("malloc failed !!!");
+ return;
+ }
+ int maskStrLength = 7 + 10 + 1;
+ char *p_maskStr = malloc(maskStrLength);
+ if (p_maskStr == NULL){
+ free(p_buf);
+ LOGE("malloc failed !!!");
+ return;
+ }
+ int fileDescriptor = inotify_init();
+ if (fileDescriptor < 0){
+ free(p_buf);
+ free(p_maskStr);
+ LOGE("inotify_init failed !!!");
+ return;
+ }
+
+ int watchDescriptor = inotify_add_watch(fileDescriptor, observer_file_path, IN_ALL_EVENTS);
+ if (watchDescriptor < 0){
+ free(p_buf);
+ free(p_maskStr);
+ LOGE("inotify_add_watch failed !!!");
+ return;
+ }
+
+
+ while(1){
+ size_t readBytes = read(fileDescriptor, p_buf, sizeof(struct inotify_event));
+ if (4 == ((struct inotify_event *) p_buf)->mask){
+ LOGE("Watched >>>>OBSERVER<<<< has been ready...");
+ free(p_maskStr);
+ free(p_buf);
+ return;
+ }
+ }
+}
+
+void notify_daemon_observer(unsigned char is_persistent, char* observer_file_path){
+ if(!is_persistent){
+ int lockFileDescriptor = open(observer_file_path, O_RDONLY);
+ while(lockFileDescriptor == -1){
+ lockFileDescriptor = open(observer_file_path, O_RDONLY);
+ }
+ }
+ remove(observer_file_path);
+}
+
+notify_and_waitfor(char *observer_self_path, char *observer_daemon_path){
+ int observer_self_descriptor = open(observer_self_path, O_RDONLY);
+ if (observer_self_descriptor == -1){
+ observer_self_descriptor = open(observer_self_path, O_CREAT, S_IRUSR | S_IWUSR);
+ }
+ int observer_daemon_descriptor = open(observer_daemon_path, O_RDONLY);
+ while (observer_daemon_descriptor == -1){
+ usleep(1000);
+ observer_daemon_descriptor = open(observer_daemon_path, O_RDONLY);
+ }
+ remove(observer_daemon_path);
+ LOGE("Watched >>>>OBSERVER<<<< has been ready...");
+}
+
+
+/**
+ * Lock the file, this is block method.
+ */
+int lock_file(char* lock_file_path){
+ LOGD("start try to lock file >> %s <<", lock_file_path);
+ int lockFileDescriptor = open(lock_file_path, O_RDONLY);
+ if (lockFileDescriptor == -1){
+ lockFileDescriptor = open(lock_file_path, O_CREAT, S_IRUSR);
+ }
+ int lockRet = flock(lockFileDescriptor, LOCK_EX);
+ if (lockRet == -1){
+ LOGE("lock file failed >> %s <<", lock_file_path);
+ return 0;
+ }else{
+ LOGD("lock file success >> %s <<", lock_file_path);
+ return 1;
+ }
+}
+
+
+JNIEXPORT void JNICALL Java_com_marswin89_marsdaemon_nativ_NativeDaemonAPI21_doDaemon(JNIEnv *env, jobject jobj, jstring indicatorSelfPath, jstring indicatorDaemonPath, jstring observerSelfPath, jstring observerDaemonPath){
+ if(indicatorSelfPath == NULL || indicatorDaemonPath == NULL || observerSelfPath == NULL || observerDaemonPath == NULL){
+ LOGE("parameters cannot be NULL !");
+ return ;
+ }
+
+ char* indicator_self_path = (char*)(*env)->GetStringUTFChars(env, indicatorSelfPath, 0);
+ char* indicator_daemon_path = (char*)(*env)->GetStringUTFChars(env, indicatorDaemonPath, 0);
+ char* observer_self_path = (char*)(*env)->GetStringUTFChars(env, observerSelfPath, 0);
+ char* observer_daemon_path = (char*)(*env)->GetStringUTFChars(env, observerDaemonPath, 0);
+
+ int lock_status = 0;
+ int try_time = 0;
+ while(try_time < 3 && !(lock_status = lock_file(indicator_self_path))){
+ try_time++;
+ LOGD("Persistent lock myself failed and try again as %d times", try_time);
+ usleep(10000);
+ }
+ if(!lock_status){
+ LOGE("Persistent lock myself failed and exit");
+ return ;
+ }
+
+// notify_daemon_observer(observer_daemon_path);
+// waitfor_self_observer(observer_self_path);
+ notify_and_waitfor(observer_self_path, observer_daemon_path);
+
+ lock_status = lock_file(indicator_daemon_path);
+ if(lock_status){
+ LOGE("Watch >>>>DAEMON<<<<< Daed !!");
+ remove(observer_self_path);// it`s important ! to prevent from deadlock
+ java_callback(env, jobj, DAEMON_CALLBACK_NAME);
+ }
+
+}
View
16 LibMarsdaemon/jni/log.h
@@ -0,0 +1,16 @@
+/*
+ * File : daemon_below20.c
+ * Author : Guoyang3
+ * Date : Aug. 14, 2015
+ * Description : for easy log.
+ */
+
+#include <jni.h>
+#include <android/log.h>
+
+#define TAG "Daemon"
+
+#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__)
+#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__)
+#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, TAG, __VA_ARGS__)
+#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__)
View
BIN LibMarsdaemon/libs/armeabi-v7a/libdaemon_api20.so
Binary file not shown.
View
BIN LibMarsdaemon/libs/armeabi-v7a/libdaemon_api21.so
Binary file not shown.
View
BIN LibMarsdaemon/libs/armeabi/libdaemon_api20.so
Binary file not shown.
View
BIN LibMarsdaemon/libs/armeabi/libdaemon_api21.so
Binary file not shown.
View
BIN LibMarsdaemon/libs/x86/libdaemon_api20.so
Binary file not shown.
View
BIN LibMarsdaemon/libs/x86/libdaemon_api21.so
Binary file not shown.
View
26 LibMarsdaemon/proguard-rules.pro
@@ -0,0 +1,26 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /Users/guoyang/Developer/android-sdk-macosx/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+-keep class com.marswin89.marsdaemon.NativeDaemonBase{*;}
+-keep class com.marswin89.marsdaemon.nativ.NativeDaemonAPI20{*;}
+-keep class com.marswin89.marsdaemon.nativ.NativeDaemonAPI21{*;}
+-keep class com.marswin89.marsdaemon.DaemonApplication{*;}
+-keep class com.marswin89.marsdaemon.DaemonClient{*;}
+-keepattributes Exceptions,InnerClasses,...
+-keep class com.marswin89.marsdaemon.DaemonConfigurations{*;}
+-keep class com.marswin89.marsdaemon.DaemonConfigurations$*{*;}
View
11 LibMarsdaemon/src/main/AndroidManifest.xml
@@ -0,0 +1,11 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.marswin89.marsdaemon">
+
+ <application
+ android:allowBackup="true"
+ android:label="@string/app_name"
+ android:supportsRtl="true">
+
+ </application>
+
+</manifest>
View
BIN LibMarsdaemon/src/main/assets/armeabi-v7a/daemon
Binary file not shown.
View
BIN LibMarsdaemon/src/main/assets/armeabi/daemon
Binary file not shown.
View
BIN LibMarsdaemon/src/main/assets/x86/daemon
Binary file not shown.
View
54 LibMarsdaemon/src/main/java/com/marswin89/marsdaemon/DaemonApplication.java
@@ -0,0 +1,54 @@
+package com.marswin89.marsdaemon;
+
+import android.app.Application;
+import android.content.Context;
+
+/**
+ * make your Application extends it
+ * @author Mars
+ *
+ */
+public abstract class DaemonApplication extends Application{
+ /**
+ * Daemon SDK needs the Daemon Configurations contains two process informations</br>
+ * see {@link DaemonConfigurations} and {@link DaemonConfigurations.DaemonConfiguration}
+ *
+ * @return DaemonConfigurations
+ */
+ protected abstract DaemonConfigurations getDaemonConfigurations();
+
+
+
+ private IDaemonClient mDaemonClient;
+ public DaemonApplication(){
+ mDaemonClient = new DaemonClient(getDaemonConfigurations());
+ }
+
+
+ /**
+ * order to prevent performing super.attachBaseContext() by child class</br>
+ * if do it, it will cause the IllegalStateException if a base context has already been set.
+ */
+ private boolean mHasAttachBaseContext = false;
+
+ @Override
+ public final void attachBaseContext(Context base) {
+ if(mHasAttachBaseContext){
+ return ;
+ }
+ mHasAttachBaseContext = true;
+ super.attachBaseContext(base);
+ mDaemonClient.onAttachBaseContext(base);
+ attachBaseContextByDaemon(base);
+ }
+
+ /**
+ * instead of {{@link #attachBaseContext(Context)}, you can override this.</br>
+ * @param base
+ */
+ public void attachBaseContextByDaemon(Context base){
+
+ }
+
+
+}
View
110 LibMarsdaemon/src/main/java/com/marswin89/marsdaemon/DaemonClient.java
@@ -0,0 +1,110 @@
+package com.marswin89.marsdaemon;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+
+/**
+ *
+ * @author Mars
+ *
+ */
+public class DaemonClient implements IDaemonClient{
+ private DaemonConfigurations mConfigurations;
+ public DaemonClient(DaemonConfigurations configurations) {
+ this.mConfigurations = configurations;
+ }
+ @Override
+ public void onAttachBaseContext(Context base) {
+ initDaemon(base);
+ }
+
+
+ private final String DAEMON_PERMITTING_SP_FILENAME = "d_permit";
+ private final String DAEMON_PERMITTING_SP_KEY = "permitted";
+
+
+ private BufferedReader mBufferedReader;//release later to save time
+
+
+ /**
+ * do some thing about daemon
+ * @param base
+ */
+ private void initDaemon(Context base) {
+ if(!isDaemonPermitting(base) || mConfigurations == null){
+ return ;
+ }
+ String processName = getProcessName();
+ String packageName = base.getPackageName();
+
+ if(processName.startsWith(mConfigurations.PERSISTENT_CONFIG.PROCESS_NAME)){
+ IDaemonStrategy.Fetcher.fetchStrategy().onPersistentCreate(base, mConfigurations);
+ }else if(processName.startsWith(mConfigurations.DAEMON_ASSISTANT_CONFIG.PROCESS_NAME)){
+ IDaemonStrategy.Fetcher.fetchStrategy().onDaemonAssistantCreate(base, mConfigurations);
+ }else if(processName.startsWith(packageName)){
+ IDaemonStrategy.Fetcher.fetchStrategy().onInitialization(base);
+ }
+
+ releaseIO();
+ }
+
+
+ /* spend too much time !! 60+ms
+ private String getProcessName(){
+ ActivityManager am = (ActivityManager) this.getSystemService(Context.ACTIVITY_SERVICE);
+ int pid = android.os.Process.myPid();
+ List<RunningAppProcessInfo> infos = am.getRunningAppProcesses();
+ for (int i = 0; i < infos.size(); i++) {
+ RunningAppProcessInfo info = infos.get(i);
+ if(pid == info.pid){
+ return info.processName;
+ }
+ }
+ return null;
+ }
+ */
+
+ private String getProcessName() {
+ try {
+ File file = new File("/proc/" + android.os.Process.myPid() + "/" + "cmdline");
+ mBufferedReader = new BufferedReader(new FileReader(file));
+ return mBufferedReader.readLine();
+ } catch (Exception e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ /**
+ * release reader IO
+ */
+ private void releaseIO(){
+ if(mBufferedReader != null){
+ try {
+ mBufferedReader.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ mBufferedReader = null;
+ }
+ }
+
+ private boolean isDaemonPermitting(Context context){
+ SharedPreferences sp = context.getSharedPreferences(DAEMON_PERMITTING_SP_FILENAME, Context.MODE_PRIVATE);
+ return sp.getBoolean(DAEMON_PERMITTING_SP_KEY, true);
+ }
+
+ protected boolean setDaemonPermiiting(Context context, boolean isPermitting) {
+ SharedPreferences sp = context.getSharedPreferences(DAEMON_PERMITTING_SP_FILENAME, Context.MODE_PRIVATE);
+ Editor editor = sp.edit();
+ editor.putBoolean(DAEMON_PERMITTING_SP_KEY, isPermitting);
+ return editor.commit();
+ }
+
+}
View
59 LibMarsdaemon/src/main/java/com/marswin89/marsdaemon/DaemonConfigurations.java
@@ -0,0 +1,59 @@
+package com.marswin89.marsdaemon;
+
+import android.content.Context;
+
+/**
+ * the configurations of Daemon SDK, contains two process configuration.
+ * @author Mars
+ *
+ */
+public class DaemonConfigurations {
+
+ public final DaemonConfiguration PERSISTENT_CONFIG;
+ public final DaemonConfiguration DAEMON_ASSISTANT_CONFIG;
+ public final DaemonListener LISTENER;
+
+ public DaemonConfigurations(DaemonConfiguration persistentConfig, DaemonConfiguration daemonAssistantConfig){
+ this.PERSISTENT_CONFIG = persistentConfig;
+ this.DAEMON_ASSISTANT_CONFIG = daemonAssistantConfig;
+ this.LISTENER = null;
+ }
+
+ public DaemonConfigurations(DaemonConfiguration persistentConfig, DaemonConfiguration daemonAssistantConfig, DaemonListener listener){
+ this.PERSISTENT_CONFIG = persistentConfig;
+ this.DAEMON_ASSISTANT_CONFIG = daemonAssistantConfig;
+ this.LISTENER = listener;
+ }
+
+
+
+ /**
+ * the configuration of a daemon process, contains process name, service name and receiver name if Android 6.0
+ * @author guoyang
+ *
+ */
+ public static class DaemonConfiguration{
+
+ public final String PROCESS_NAME;
+ public final String SERVICE_NAME;
+ public final String RECEIVER_NAME;
+
+ public DaemonConfiguration(String processName, String serviceName, String receiverName){
+ this.PROCESS_NAME = processName;
+ this.SERVICE_NAME = serviceName;
+ this.RECEIVER_NAME = receiverName;
+ }
+ }
+
+ /**
+ * listener of daemon for external
+ *
+ * @author Mars
+ *
+ */
+ public interface DaemonListener {
+ void onPersistentStart(Context context);
+ void onDaemonAssistantStart(Context context);
+ void onWatchDaemonDaed();
+ }
+}
View
20 LibMarsdaemon/src/main/java/com/marswin89/marsdaemon/IDaemonClient.java
@@ -0,0 +1,20 @@
+package com.marswin89.marsdaemon;
+
+import android.content.Context;
+
+/**
+ *
+ * @author Mars
+ *
+ */
+public interface IDaemonClient {
+ /**
+ * override this method by {@link android.app.Application}</br></br>
+ * ****************************************************************</br>
+ * <b>DO super.attchBaseContext() first !</b></br>
+ * ****************************************************************</br>
+ *
+ * @param base
+ */
+ void onAttachBaseContext(Context base);
+}
View
97 LibMarsdaemon/src/main/java/com/marswin89/marsdaemon/IDaemonStrategy.java
@@ -0,0 +1,97 @@
+package com.marswin89.marsdaemon;
+
+import com.marswin89.marsdaemon.strategy.DaemonStrategy21;
+import com.marswin89.marsdaemon.strategy.DaemonStrategy22;
+import com.marswin89.marsdaemon.strategy.DaemonStrategy23;
+import com.marswin89.marsdaemon.strategy.DaemonStrategyUnder21;
+import com.marswin89.marsdaemon.strategy.DaemonStrategyXiaomi;
+
+import android.content.Context;
+import android.os.Build;
+
+/**
+ * define strategy method
+ *
+ * @author Mars
+ *
+ */
+public interface IDaemonStrategy {
+ /**
+ * Initialization some files or other when 1st time
+ *
+ * @param context
+ * @return
+ */
+ boolean onInitialization(Context context);
+
+ /**
+ * when Persistent process create
+ *
+ * @param context
+ * @param configs
+ */
+ void onPersistentCreate(Context context, DaemonConfigurations configs);
+
+ /**
+ * when DaemonAssistant process create
+ * @param context
+ * @param configs
+ */
+ void onDaemonAssistantCreate(Context context, DaemonConfigurations configs);
+
+ /**
+ * when watches the process dead which it watched
+ */
+ void onDaemonDead();
+
+
+
+ /**
+ * all about strategy on different device here
+ *
+ * @author Mars
+ *
+ */
+ public static class Fetcher {
+
+ private static IDaemonStrategy mDaemonStrategy;
+
+ /**
+ * fetch the strategy for this device
+ *
+ * @return the daemon strategy for this device
+ */
+ static IDaemonStrategy fetchStrategy() {
+ if (mDaemonStrategy != null) {
+ return mDaemonStrategy;
+ }
+ int sdk = Build.VERSION.SDK_INT;
+ switch (sdk) {
+ case 23:
+ mDaemonStrategy = new DaemonStrategy23();
+ break;
+
+ case 22:
+ mDaemonStrategy = new DaemonStrategy22();
+ break;
+
+ case 21:
+ if("MX4 Pro".equalsIgnoreCase(Build.MODEL)){
+ mDaemonStrategy = new DaemonStrategyUnder21();
+ }else{
+ mDaemonStrategy = new DaemonStrategy21();
+ }
+ break;
+
+ default:
+ if(Build.MODEL != null && Build.MODEL.toLowerCase().startsWith("mi")){
+ mDaemonStrategy = new DaemonStrategyXiaomi();
+ }else{
+ mDaemonStrategy = new DaemonStrategyUnder21();
+ }
+ break;
+ }
+ return mDaemonStrategy;
+ }
+ }
+}
View
28 LibMarsdaemon/src/main/java/com/marswin89/marsdaemon/NativeDaemonBase.java
@@ -0,0 +1,28 @@
+package com.marswin89.marsdaemon;
+
+import android.content.Context;
+
+/**
+ * native base class
+ *
+ * @author Mars
+ *
+ */
+public class NativeDaemonBase {
+ /**
+ * used for native
+ */
+ protected Context mContext;
+
+ public NativeDaemonBase(Context context){
+ this.mContext = context;
+ }
+
+ /**
+ * native call back
+ */
+ protected void onDaemonDead(){
+ IDaemonStrategy.Fetcher.fetchStrategy().onDaemonDead();
+ }
+
+}
View
35 LibMarsdaemon/src/main/java/com/marswin89/marsdaemon/PackageUtils.java
@@ -0,0 +1,35 @@
+package com.marswin89.marsdaemon;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.PackageManager;
+
+/**
+ * Utils to prevent component from third-party app forbidding
+ *
+ * @author Mars
+ *
+ */
+public class PackageUtils {
+ /**
+ * set the component in our package default
+ * @param context
+ * @param componentClassName
+ */
+ public static void setComponentDefault(Context context, String componentClassName){
+ PackageManager pm = context.getPackageManager();
+ ComponentName componentName = new ComponentName(context.getPackageName(), componentClassName);
+ pm.setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, PackageManager.DONT_KILL_APP);
+ }
+
+ /**
+ * get the component in our package default
+ * @param context
+ * @param componentClassName
+ */
+ public static boolean isComponentDefault(Context context, String componentClassName){
+ PackageManager pm = context.getPackageManager();
+ ComponentName componentName = new ComponentName(context.getPackageName(), componentClassName);
+ return pm.getComponentEnabledSetting(componentName) == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
+ }
+}
View
28 LibMarsdaemon/src/main/java/com/marswin89/marsdaemon/nativ/NativeDaemonAPI20.java
@@ -0,0 +1,28 @@
+package com.marswin89.marsdaemon.nativ;
+
+import com.marswin89.marsdaemon.NativeDaemonBase;
+
+import android.content.Context;
+
+/**
+ * native code to watch each other when api under 20 (contains 20)
+ * @author Mars
+ *
+ */
+public class NativeDaemonAPI20 extends NativeDaemonBase {
+
+ public NativeDaemonAPI20(Context context) {
+ super(context);
+ }
+
+ static{
+ try {
+ System.loadLibrary("daemon_api20");
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public native void doDaemon(String pkgName, String svcName, String daemonPath);
+
+}
View
27 LibMarsdaemon/src/main/java/com/marswin89/marsdaemon/nativ/NativeDaemonAPI21.java
@@ -0,0 +1,27 @@
+package com.marswin89.marsdaemon.nativ;
+
+import com.marswin89.marsdaemon.NativeDaemonBase;
+
+import android.content.Context;
+
+/**
+ * native code to watch each other when api over 21 (contains 21)
+ * @author Mars
+ *
+ */
+public class NativeDaemonAPI21 extends NativeDaemonBase{
+
+ public NativeDaemonAPI21(Context context) {
+ super(context);
+ }
+
+ static{
+ try {
+ System.loadLibrary("daemon_api21");
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public native void doDaemon(String indicatorSelfPath, String indicatorDaemonPath, String observerSelfPath, String observerDaemonPath);
+}
View
144 LibMarsdaemon/src/main/java/com/marswin89/marsdaemon/strategy/DaemonStrategy21.java
@@ -0,0 +1,144 @@
+package com.marswin89.marsdaemon.strategy;
+
+import java.io.File;
+import java.io.IOException;
+
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.os.SystemClock;
+
+import com.marswin89.marsdaemon.DaemonConfigurations;
+import com.marswin89.marsdaemon.IDaemonStrategy;
+import com.marswin89.marsdaemon.nativ.NativeDaemonAPI21;
+/**
+ * the strategy in android API 21.
+ *
+ * @author Mars
+ *
+ */
+public class DaemonStrategy21 implements IDaemonStrategy{
+ private final static String INDICATOR_DIR_NAME = "indicators";
+ private final static String INDICATOR_PERSISTENT_FILENAME = "indicator_p";
+ private final static String INDICATOR_DAEMON_ASSISTANT_FILENAME = "indicator_d";
+ private final static String OBSERVER_PERSISTENT_FILENAME = "observer_p";
+ private final static String OBSERVER_DAEMON_ASSISTANT_FILENAME = "observer_d";
+
+ private AlarmManager mAlarmManager;
+ private PendingIntent mPendingIntent;
+ private DaemonConfigurations mConfigs;
+
+ @Override
+ public boolean onInitialization(Context context) {
+ return initIndicators(context);
+ }
+
+ @Override
+ public void onPersistentCreate(final Context context, DaemonConfigurations configs) {
+ Intent intent = new Intent();
+ ComponentName componentName = new ComponentName(context.getPackageName(), configs.DAEMON_ASSISTANT_CONFIG.SERVICE_NAME);
+ intent.setComponent(componentName);
+ context.startService(intent);
+
+ initAlarm(context, configs.PERSISTENT_CONFIG.SERVICE_NAME);
+
+ Thread t = new Thread(){
+ @Override
+ public void run() {
+ File indicatorDir = context.getDir(INDICATOR_DIR_NAME, Context.MODE_PRIVATE);
+ new NativeDaemonAPI21(context).doDaemon(
+ new File(indicatorDir, INDICATOR_PERSISTENT_FILENAME).getAbsolutePath(),
+ new File(indicatorDir, INDICATOR_DAEMON_ASSISTANT_FILENAME).getAbsolutePath(),
+ new File(indicatorDir, OBSERVER_PERSISTENT_FILENAME).getAbsolutePath(),
+ new File(indicatorDir, OBSERVER_DAEMON_ASSISTANT_FILENAME).getAbsolutePath());
+ }
+ };
+ t.setPriority(Thread.MAX_PRIORITY);
+ t.start();
+
+ if(configs != null && configs.LISTENER != null){
+ this.mConfigs = configs;
+ configs.LISTENER.onPersistentStart(context);
+ }
+ }
+
+ @Override
+ public void onDaemonAssistantCreate(final Context context, DaemonConfigurations configs) {
+ Intent intent = new Intent();
+ ComponentName componentName = new ComponentName(context.getPackageName(), configs.PERSISTENT_CONFIG.SERVICE_NAME);
+ intent.setComponent(componentName);
+ context.startService(intent);
+
+ initAlarm(context, configs.PERSISTENT_CONFIG.SERVICE_NAME);
+
+ Thread t = new Thread(){
+ public void run() {
+ File indicatorDir = context.getDir(INDICATOR_DIR_NAME, Context.MODE_PRIVATE);
+ new NativeDaemonAPI21(context).doDaemon(
+ new File(indicatorDir, INDICATOR_DAEMON_ASSISTANT_FILENAME).getAbsolutePath(),
+ new File(indicatorDir, INDICATOR_PERSISTENT_FILENAME).getAbsolutePath(),
+ new File(indicatorDir, OBSERVER_DAEMON_ASSISTANT_FILENAME).getAbsolutePath(),
+ new File(indicatorDir, OBSERVER_PERSISTENT_FILENAME).getAbsolutePath());
+ };
+ };
+ t.setPriority(Thread.MAX_PRIORITY);
+ t.start();
+
+ if(configs != null && configs.LISTENER != null){
+ this.mConfigs = configs;
+ configs.LISTENER.onDaemonAssistantStart(context);
+ }
+ }
+
+ @Override
+ public void onDaemonDead() {
+ mAlarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime(), 100, mPendingIntent);
+
+ if(mConfigs != null && mConfigs.LISTENER != null){
+ mConfigs.LISTENER.onWatchDaemonDaed();
+ }
+ android.os.Process.killProcess(android.os.Process.myPid());
+ }
+
+
+ private void initAlarm(Context context, String serviceName){
+ if(mAlarmManager == null){
+ mAlarmManager = ((AlarmManager)context.getSystemService(Context.ALARM_SERVICE));
+ }
+ if(mPendingIntent == null){
+ Intent intent = new Intent();
+ ComponentName component = new ComponentName(context.getPackageName(), serviceName);
+ intent.setComponent(component);
+ intent.setFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
+ mPendingIntent = PendingIntent.getService(context, 0, intent, 0);
+ }
+ mAlarmManager.cancel(mPendingIntent);
+ }
+
+
+ private boolean initIndicators(Context context){
+ File dirFile = context.getDir(INDICATOR_DIR_NAME, Context.MODE_PRIVATE);
+ if(!dirFile.exists()){
+ dirFile.mkdirs();
+ }
+ try {
+ createNewFile(dirFile, INDICATOR_PERSISTENT_FILENAME);
+ createNewFile(dirFile, INDICATOR_DAEMON_ASSISTANT_FILENAME);
+ return true;
+ } catch (IOException e) {
+ e.printStackTrace();
+ return false;
+ }
+ }
+
+
+ private void createNewFile(File dirFile, String fileName) throws IOException{
+ File file = new File(dirFile, fileName);
+ if(!file.exists()){
+ file.createNewFile();
+ }
+ }
+
+}
View
204 LibMarsdaemon/src/main/java/com/marswin89/marsdaemon/strategy/DaemonStrategy22.java
@@ -0,0 +1,204 @@
+package com.marswin89.marsdaemon.strategy;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+
+import android.annotation.SuppressLint;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.RemoteException;
+import android.util.Log;
+
+import com.marswin89.marsdaemon.DaemonConfigurations;
+import com.marswin89.marsdaemon.IDaemonStrategy;
+import com.marswin89.marsdaemon.nativ.NativeDaemonAPI21;
+/**
+ * the strategy in android API 22.
+ *
+ * @author Mars
+ *
+ */
+public class DaemonStrategy22 implements IDaemonStrategy{
+ private final static String INDICATOR_DIR_NAME = "indicators";
+ private final static String INDICATOR_PERSISTENT_FILENAME = "indicator_p";
+ private final static String INDICATOR_DAEMON_ASSISTANT_FILENAME = "indicator_d";
+ private final static String OBSERVER_PERSISTENT_FILENAME = "observer_p";
+ private final static String OBSERVER_DAEMON_ASSISTANT_FILENAME = "observer_d";
+
+ private IBinder mRemote;
+ private Parcel mServiceData;
+ private DaemonConfigurations mConfigs;
+
+ @Override
+ public boolean onInitialization(Context context) {
+ return initIndicatorFiles(context);
+ }
+
+ @Override
+ public void onPersistentCreate(final Context context, DaemonConfigurations configs) {
+ initAmsBinder();
+ initServiceParcel(context, configs.DAEMON_ASSISTANT_CONFIG.SERVICE_NAME);
+ startServiceByAmsBinder();
+
+ Thread t = new Thread(){
+ public void run() {
+ File indicatorDir = context.getDir(INDICATOR_DIR_NAME, Context.MODE_PRIVATE);
+ new NativeDaemonAPI21(context).doDaemon(
+ new File(indicatorDir, INDICATOR_PERSISTENT_FILENAME).getAbsolutePath(),
+ new File(indicatorDir, INDICATOR_DAEMON_ASSISTANT_FILENAME).getAbsolutePath(),
+ new File(indicatorDir, OBSERVER_PERSISTENT_FILENAME).getAbsolutePath(),
+ new File(indicatorDir, OBSERVER_DAEMON_ASSISTANT_FILENAME).getAbsolutePath());
+ };
+ };
+ t.start();
+
+ if(configs != null && configs.LISTENER != null){
+ this.mConfigs = configs;
+ configs.LISTENER.onPersistentStart(context);
+ }
+ }
+
+ @Override
+ public void onDaemonAssistantCreate(final Context context, DaemonConfigurations configs) {
+ initAmsBinder();
+ initServiceParcel(context, configs.PERSISTENT_CONFIG.SERVICE_NAME);
+ startServiceByAmsBinder();
+
+ Thread t = new Thread(){
+ public void run() {
+ File indicatorDir = context.getDir(INDICATOR_DIR_NAME, Context.MODE_PRIVATE);
+ new NativeDaemonAPI21(context).doDaemon(
+ new File(indicatorDir, INDICATOR_DAEMON_ASSISTANT_FILENAME).getAbsolutePath(),
+ new File(indicatorDir, INDICATOR_PERSISTENT_FILENAME).getAbsolutePath(),
+ new File(indicatorDir, OBSERVER_DAEMON_ASSISTANT_FILENAME).getAbsolutePath(),
+ new File(indicatorDir, OBSERVER_PERSISTENT_FILENAME).getAbsolutePath());
+ };
+ };
+ t.start();
+
+ if(configs != null && configs.LISTENER != null){
+ this.mConfigs = configs;
+ configs.LISTENER.onDaemonAssistantStart(context);
+ }
+
+ }
+
+
+ @Override
+ public void onDaemonDead() {
+ if(startServiceByAmsBinder()){
+
+ if(mConfigs != null && mConfigs.LISTENER != null){
+ mConfigs.LISTENER.onWatchDaemonDaed();
+ }
+
+ android.os.Process.killProcess(android.os.Process.myPid());
+ }
+ }
+
+
+ private void initAmsBinder(){
+ Class<?> activityManagerNative;
+ try {
+ activityManagerNative = Class.forName("android.app.ActivityManagerNative");
+ Object amn = activityManagerNative.getMethod("getDefault").invoke(activityManagerNative);
+ Field mRemoteField = amn.getClass().getDeclaredField("mRemote");
+ mRemoteField.setAccessible(true);
+ mRemote = (IBinder) mRemoteField.get(amn);
+ } catch (ClassNotFoundException e) {
+ e.printStackTrace();
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ } catch (IllegalArgumentException e) {
+ e.printStackTrace();
+ } catch (InvocationTargetException e) {
+ e.printStackTrace();
+ } catch (NoSuchMethodException e) {
+ e.printStackTrace();
+ } catch (NoSuchFieldException e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ @SuppressLint("Recycle")// when process dead, we should save time to restart and kill self, don`t take a waste of time to recycle
+ private void initServiceParcel(Context context, String serviceName){
+ Intent intent = new Intent();
+ ComponentName component = new ComponentName(context.getPackageName(), serviceName);
+ intent.setComponent(component);
+
+ /*
+ //get ContextImpl instance
+// Object contextImpl = ((Application)context.getApplicationContext()).getBaseContext();
+ //this context is ContextImpl, get MainThread instance immediately
+ Field mainThreadField = context.getClass().getDeclaredField("mMainThread");
+ mainThreadField.setAccessible(true);
+ Object mainThread = mainThreadField.get(context);
+ //get ApplicationThread instance
+ Object applicationThread = mainThread.getClass().getMethod("getApplicationThread").invoke(mainThread);
+ //get Binder
+ Binder callerBinder = (Binder) (applicationThread.getClass().getMethod("asBinder").invoke(applicationThread));
+ */
+
+ //get handle
+// UserHandle userHandle = android.os.Process.myUserHandle();
+// int handle = (Integer) userHandle.getClass().getMethod("getIdentifier").invoke(userHandle);
+
+ //write pacel
+ mServiceData = Parcel.obtain();
+ mServiceData.writeInterfaceToken("android.app.IActivityManager");
+ mServiceData.writeStrongBinder(null);
+// mServiceData.writeStrongBinder(callerBinder);
+ intent.writeToParcel(mServiceData, 0);
+ mServiceData.writeString(null);
+// mServiceData.writeString(intent.resolveTypeIfNeeded(context.getContentResolver()));
+ mServiceData.writeInt(0);
+// mServiceData.writeInt(handle);
+
+ }
+
+
+ private boolean startServiceByAmsBinder(){
+ try {
+ if(mRemote == null || mServiceData == null){
+ Log.e("Daemon", "REMOTE IS NULL or PARCEL IS NULL !!!");
+ return false;
+ }
+ mRemote.transact(34, mServiceData, null, 0);//START_SERVICE_TRANSACTION = 34
+ return true;
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ return false;
+ }
+ }
+
+
+
+
+ private boolean initIndicatorFiles(Context context){
+ File dirFile = context.getDir(INDICATOR_DIR_NAME, Context.MODE_PRIVATE);
+ if(!dirFile.exists()){
+ dirFile.mkdirs();
+ }
+ try {
+ createNewFile(dirFile, INDICATOR_PERSISTENT_FILENAME);
+ createNewFile(dirFile, INDICATOR_DAEMON_ASSISTANT_FILENAME);
+ return true;
+ } catch (IOException e) {
+ e.printStackTrace();
+ return false;
+ }
+ }
+
+ private void createNewFile(File dirFile, String fileName) throws IOException{
+ File file = new File(dirFile, fileName);
+ if(!file.exists()){
+ file.createNewFile();
+ }
+ }
+}
View
218 LibMarsdaemon/src/main/java/com/marswin89/marsdaemon/strategy/DaemonStrategy23.java
@@ -0,0 +1,218 @@
+package com.marswin89.marsdaemon.strategy;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.RemoteException;
+import android.util.Log;
+
+import com.marswin89.marsdaemon.DaemonConfigurations;
+import com.marswin89.marsdaemon.IDaemonStrategy;
+import com.marswin89.marsdaemon.nativ.NativeDaemonAPI21;
+/**
+ * the strategy in android API 23.
+ *
+ * @author Mars
+ *
+ */
+public class DaemonStrategy23 implements IDaemonStrategy{
+ private final static String INDICATOR_DIR_NAME = "indicators";
+ private final static String INDICATOR_PERSISTENT_FILENAME = "indicator_p";
+ private final static String INDICATOR_DAEMON_ASSISTANT_FILENAME = "indicator_d";
+ private final static String OBSERVER_PERSISTENT_FILENAME = "observer_p";
+ private final static String OBSERVER_DAEMON_ASSISTANT_FILENAME = "observer_d";
+
+ private IBinder mRemote;
+ private Parcel mBroadcastData;
+ private DaemonConfigurations mConfigs;
+
+ @Override
+ public boolean onInitialization(Context context) {
+ return initIndicatorFiles(context);
+ }
+
+ @Override
+ public void onPersistentCreate(final Context context, DaemonConfigurations configs) {
+ initAmsBinder();
+ initBroadcastParcel(context, configs.DAEMON_ASSISTANT_CONFIG.RECEIVER_NAME);
+ sendBroadcastByAmsBinder();
+
+ Thread t = new Thread(){
+ public void run() {
+ File indicatorDir = context.getDir(INDICATOR_DIR_NAME, Context.MODE_PRIVATE);
+ new NativeDaemonAPI21(context).doDaemon(
+ new File(indicatorDir, INDICATOR_PERSISTENT_FILENAME).getAbsolutePath(),
+ new File(indicatorDir, INDICATOR_DAEMON_ASSISTANT_FILENAME).getAbsolutePath(),
+ new File(indicatorDir, OBSERVER_PERSISTENT_FILENAME).getAbsolutePath(),
+ new File(indicatorDir, OBSERVER_DAEMON_ASSISTANT_FILENAME).getAbsolutePath());
+ };
+ };
+ t.start();
+
+ ComponentName componentName = new ComponentName(context.getPackageName(), configs.PERSISTENT_CONFIG.SERVICE_NAME);
+ Intent intent = new Intent();
+ intent.setComponent(componentName);
+ context.startService(intent);
+
+ if(configs != null && configs.LISTENER != null){
+ this.mConfigs = configs;
+ configs.LISTENER.onPersistentStart(context);
+ }
+ }
+
+ @Override
+ public void onDaemonAssistantCreate(final Context context, DaemonConfigurations configs) {
+ initAmsBinder();
+ initBroadcastParcel(context, configs.PERSISTENT_CONFIG.RECEIVER_NAME);
+ sendBroadcastByAmsBinder();
+
+ Thread t = new Thread(){
+ public void run() {
+ File indicatorDir = context.getDir(INDICATOR_DIR_NAME, Context.MODE_PRIVATE);
+ new NativeDaemonAPI21(context).doDaemon(
+ new File(indicatorDir, INDICATOR_DAEMON_ASSISTANT_FILENAME).getAbsolutePath(),
+ new File(indicatorDir, INDICATOR_PERSISTENT_FILENAME).getAbsolutePath(),
+ new File(indicatorDir, OBSERVER_DAEMON_ASSISTANT_FILENAME).getAbsolutePath(),
+ new File(indicatorDir, OBSERVER_PERSISTENT_FILENAME).getAbsolutePath());
+ };
+ };
+ t.start();
+
+ ComponentName componentName = new ComponentName(context.getPackageName(), configs.DAEMON_ASSISTANT_CONFIG.SERVICE_NAME);
+ Intent intent = new Intent();
+ intent.setComponent(componentName);
+ context.startService(intent);
+
+ if(configs != null && configs.LISTENER != null){
+ this.mConfigs = configs;
+ configs.LISTENER.onDaemonAssistantStart(context);
+ }
+ }
+
+
+ @Override
+ public void onDaemonDead() {
+ if(sendBroadcastByAmsBinder()){
+
+ if(mConfigs != null && mConfigs.LISTENER != null){
+ mConfigs.LISTENER.onWatchDaemonDaed();
+ }
+
+ android.os.Process.killProcess(android.os.Process.myPid());
+ }
+ }
+
+
+ private void initAmsBinder(){
+ Class<?> activityManagerNative;
+ try {
+ activityManagerNative = Class.forName("android.app.ActivityManagerNative");
+ Object amn = activityManagerNative.getMethod("getDefault").invoke(activityManagerNative);
+ Field mRemoteField = amn.getClass().getDeclaredField("mRemote");
+ mRemoteField.setAccessible(true);
+ mRemote = (IBinder) mRemoteField.get(amn);
+ } catch (ClassNotFoundException e) {
+ e.printStackTrace();
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ } catch (IllegalArgumentException e) {
+ e.printStackTrace();
+ } catch (InvocationTargetException e) {
+ e.printStackTrace();
+ } catch (NoSuchMethodException e) {
+ e.printStackTrace();
+ } catch (NoSuchFieldException e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ @SuppressLint("Recycle")// when process dead, we should save time to restart and kill self, don`t take a waste of time to recycle
+ private void initBroadcastParcel(Context context, String broadcastName){
+ Intent intent = new Intent();
+ ComponentName componentName = new ComponentName(context.getPackageName(), broadcastName);
+ intent.setComponent(componentName);
+ intent.setFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
+
+ /*
+// Object contextImpl = ((Application)context.getApplicationContext()).getBaseContext();
+ //this context is ContextImpl, get MainThread instance immediately
+ Field mainThreadField = context.getClass().getDeclaredField("mMainThread");
+ mainThreadField.setAccessible(true);
+ Object mainThread = mainThreadField.get(context);
+ //get ApplicationThread instance
+ Object applicationThread = mainThread.getClass().getMethod("getApplicationThread").invoke(mainThread);
+ //get Binder
+ Binder callerBinder = (Binder) (applicationThread.getClass().getMethod("asBinder").invoke(applicationThread));
+ */
+
+// UserHandle userHandle = android.os.Process.myUserHandle();
+// int handle = (Integer) userHandle.getClass().getMethod("getIdentifier").invoke(userHandle);
+
+ mBroadcastData = Parcel.obtain();
+ mBroadcastData.writeInterfaceToken("android.app.IActivityManager");
+// mBroadcastData.writeStrongBinder(callerBinder);
+ mBroadcastData.writeStrongBinder(null);
+ intent.writeToParcel(mBroadcastData, 0);
+ mBroadcastData.writeString(intent.resolveTypeIfNeeded(context.getContentResolver()));
+ mBroadcastData.writeStrongBinder(null);
+ mBroadcastData.writeInt(Activity.RESULT_OK);
+ mBroadcastData.writeString(null);
+ mBroadcastData.writeBundle(null);
+ mBroadcastData.writeString(null);
+ mBroadcastData.writeInt(-1);
+ mBroadcastData.writeInt(0);
+ mBroadcastData.writeInt(0);
+// mBroadcastData.writeInt(handle);
+ mBroadcastData.writeInt(0);
+ }
+
+
+ private boolean sendBroadcastByAmsBinder(){
+
+ try {
+ if(mRemote == null || mBroadcastData == null){
+ Log.e("Daemon", "REMOTE IS NULL or PARCEL IS NULL !!!");
+ return false;
+ }
+ mRemote.transact(14, mBroadcastData, null, 0);//BROADCAST_INTENT_TRANSACTION = 0x00000001 + 13
+ return true;
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ return false;
+ }
+ }
+
+
+
+ private boolean initIndicatorFiles(Context context){
+ File dirFile = context.getDir(INDICATOR_DIR_NAME, Context.MODE_PRIVATE);
+ if(!dirFile.exists()){
+ dirFile.mkdirs();
+ }
+ try {
+ createNewFile(dirFile, INDICATOR_PERSISTENT_FILENAME);
+ createNewFile(dirFile, INDICATOR_DAEMON_ASSISTANT_FILENAME);
+ return true;
+ } catch (IOException e) {
+ e.printStackTrace();
+ return false;
+ }
+ }
+
+ private void createNewFile(File dirFile, String fileName) throws IOException{
+ File file = new File(dirFile, fileName);
+ if(!file.exists()){
+ file.createNewFile();
+ }
+ }
+}
View
143 LibMarsdaemon/src/main/java/com/marswin89/marsdaemon/strategy/DaemonStrategyUnder21.java
@@ -0,0 +1,143 @@
+package com.marswin89.marsdaemon.strategy;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.AssetManager;
+import android.os.Build;
+import android.os.SystemClock;
+import android.text.TextUtils;
+
+import com.marswin89.marsdaemon.DaemonConfigurations;
+import com.marswin89.marsdaemon.IDaemonStrategy;
+import com.marswin89.marsdaemon.nativ.NativeDaemonAPI20;
+
+/**
+ * the strategy in android API below 21.
+ *
+ * @author Mars
+ *
+ */
+public class DaemonStrategyUnder21 implements IDaemonStrategy{
+ private final String BINARY_DEST_DIR_NAME = "bin";
+ private final String BINARY_FILE_NAME = "daemon";
+
+ private AlarmManager mAlarmManager;
+ private PendingIntent mPendingIntent;
+
+ @Override
+ public boolean onInitialization(Context context) {
+ return installBinary(context);
+ }
+
+ @Override
+ public void onPersistentCreate(final Context context, final DaemonConfigurations configs) {
+ initAlarm(context, configs.DAEMON_ASSISTANT_CONFIG.SERVICE_NAME);
+ Thread t = new Thread(){
+ public void run() {
+ File binaryFile = new File(context.getDir(BINARY_DEST_DIR_NAME, Context.MODE_PRIVATE), BINARY_FILE_NAME);
+ new NativeDaemonAPI20(context).doDaemon(
+ context.getPackageName(),
+ configs.DAEMON_ASSISTANT_CONFIG.SERVICE_NAME,
+ binaryFile.getAbsolutePath());
+ };
+ };
+ t.setPriority(Thread.MAX_PRIORITY);
+ t.start();
+
+ if(configs != null && configs.LISTENER != null){
+ configs.LISTENER.onPersistentStart(context);
+ }
+ }
+
+ @Override
+ public void onDaemonAssistantCreate(Context context, DaemonConfigurations configs) {
+ Intent intent = new Intent();
+ ComponentName component = new ComponentName(context.getPackageName(), configs.PERSISTENT_CONFIG.SERVICE_NAME);
+ intent.setComponent(component);
+ context.startService(intent);
+ if(configs != null && configs.LISTENER != null){
+ configs.LISTENER.onWatchDaemonDaed();
+ }
+ android.os.Process.killProcess(android.os.Process.myPid());
+ }
+
+
+ @Override
+ public void onDaemonDead() {
+ mAlarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime(), 100, mPendingIntent);
+ android.os.Process.killProcess(android.os.Process.myPid());
+ }
+
+
+ private void initAlarm(Context context, String serviceName){
+ if(mAlarmManager == null){
+ mAlarmManager = ((AlarmManager)context.getSystemService(Context.ALARM_SERVICE));
+ }
+ if(mPendingIntent == null){
+ Intent intent = new Intent();
+ ComponentName component = new ComponentName(context.getPackageName(), serviceName);
+ intent.setComponent(component);
+ intent.setFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
+ mPendingIntent = PendingIntent.getService(context, 0, intent, 0);
+ }
+ mAlarmManager.cancel(mPendingIntent);
+ }
+
+
+ private boolean installBinary(Context context){
+ String binaryDirName = null;
+ String abi = Build.CPU_ABI;
+ if (abi.startsWith("armeabi-v7a")) {
+ binaryDirName = "armeabi-v7a";
+ }else if(abi.startsWith("x86")) {
+ binaryDirName = "x86";
+ }else{
+ binaryDirName = "armeabi";
+ }
+ return install(context, BINARY_DEST_DIR_NAME, binaryDirName, BINARY_FILE_NAME);
+ }
+
+
+ private boolean install(Context context, String destDirName, String assetsDirName, String filename) {
+ File file = new File(context.getDir(destDirName, Context.MODE_PRIVATE), filename);
+ if (file.exists()) {
+ return true;
+ }
+ try {
+ copyAssets(context, (TextUtils.isEmpty(assetsDirName) ? "" : (assetsDirName + File.separator)) + filename, file, "700");
+ return true;
+ } catch (Exception e) {
+ return false;
+ }
+ }
+
+ private void copyAssets(Context context, String assetsFilename, File file, String mode) throws IOException, InterruptedException {
+ AssetManager manager = context.getAssets();
+ final InputStream is = manager.open(assetsFilename);
+ copyFile(file, is, mode);
+ }
+
+ private void copyFile(File file, InputStream is, String mode) throws IOException, InterruptedException {
+ if(!file.getParentFile().exists()){
+ file.getParentFile().mkdirs();
+ }
+ final String abspath = file.getAbsolutePath();
+ final FileOutputStream out = new FileOutputStream(file);
+ byte buf[] = new byte[1024];
+ int len;
+ while ((len = is.read(buf)) > 0) {
+ out.write(buf, 0, len);
+ }
+ out.close();
+ is.close();
+ Runtime.getRuntime().exec("chmod " + mode + " " + abspath).waitFor();
+ }
+}
View
215 LibMarsdaemon/src/main/java/com/marswin89/marsdaemon/strategy/DaemonStrategyXiaomi.java
@@ -0,0 +1,215 @@
+package com.marswin89.marsdaemon.strategy;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+
+import android.annotation.SuppressLint;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.AssetManager;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.RemoteException;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.marswin89.marsdaemon.DaemonConfigurations;
+import com.marswin89.marsdaemon.IDaemonStrategy;
+import com.marswin89.marsdaemon.nativ.NativeDaemonAPI20;
+
+/**
+ * the strategy in Mi.
+ *
+ * @author Mars
+ *
+ */
+public class DaemonStrategyXiaomi implements IDaemonStrategy{
+ private final String BINARY_DEST_DIR_NAME = "bin";
+ private final String BINARY_FILE_NAME = "daemon";
+
+ private IBinder mRemote;
+ private Parcel mServiceData;
+ private DaemonConfigurations mConfigs;
+
+ @Override
+ public boolean onInitialization(Context context) {
+ return installBinary(context);
+ }
+
+ @Override
+ public void onPersistentCreate(final Context context, final DaemonConfigurations configs) {
+ initAmsBinder();
+ initServiceParcel(context, configs.DAEMON_ASSISTANT_CONFIG.SERVICE_NAME);
+ Thread t = new Thread(){
+ public void run() {
+ File binaryFile = new File(context.getDir(BINARY_DEST_DIR_NAME, Context.MODE_PRIVATE), BINARY_FILE_NAME);
+ new NativeDaemonAPI20(context).doDaemon(
+ context.getPackageName(),
+ configs.DAEMON_ASSISTANT_CONFIG.SERVICE_NAME,
+ binaryFile.getAbsolutePath());
+ };
+ };
+ t.setPriority(Thread.MAX_PRIORITY);
+ t.start();
+
+ if(configs != null && configs.LISTENER != null){
+ this.mConfigs = configs;
+ configs.LISTENER.onPersistentStart(context);
+ }
+
+ }
+
+
+ @Override
+ public void onDaemonAssistantCreate(Context context, DaemonConfigurations configs) {
+ Intent intent = new Intent();
+ ComponentName component = new ComponentName(context.getPackageName(), configs.PERSISTENT_CONFIG.SERVICE_NAME);
+ intent.setComponent(component);
+ context.startService(intent);
+ if(configs != null && configs.LISTENER != null){
+ configs.LISTENER.onWatchDaemonDaed();
+ }
+ android.os.Process.killProcess(android.os.Process.myPid());
+ }
+
+ @Override
+ public void onDaemonDead() {
+ if(startServiceByAmsBinder()){
+
+ if(mConfigs != null && mConfigs.LISTENER != null){
+ mConfigs.LISTENER.onWatchDaemonDaed();
+ }
+
+ android.os.Process.killProcess(android.os.Process.myPid());
+ }
+ }
+
+ private void initAmsBinder(){
+ Class<?> activityManagerNative;
+ try {
+ activityManagerNative = Class.forName("android.app.ActivityManagerNative");
+ Object amn = activityManagerNative.getMethod("getDefault").invoke(activityManagerNative);
+ Field mRemoteField = amn.getClass().getDeclaredField("mRemote");
+ mRemoteField.setAccessible(true);
+ mRemote = (IBinder) mRemoteField.get(amn);
+ } catch (ClassNotFoundException e) {
+ e.printStackTrace();
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ } catch (IllegalArgumentException e) {
+ e.printStackTrace();
+ } catch (InvocationTargetException e) {
+ e.printStackTrace();
+ } catch (NoSuchMethodException e) {
+ e.printStackTrace();
+ } catch (NoSuchFieldException e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ @SuppressLint("Recycle")// when process dead, we should save time to restart and kill self, don`t take a waste of time to recycle
+ private void initServiceParcel(Context context, String serviceName){
+ Intent intent = new Intent();
+ ComponentName component = new ComponentName(context.getPackageName(), serviceName);
+ intent.setComponent(component);
+
+ /*
+ //get ContextImpl instance
+// Object contextImpl = ((Application)context.getApplicationContext()).getBaseContext();
+ //this context is ContextImpl, get MainThread instance immediately
+ Field mainThreadField = context.getClass().getDeclaredField("mMainThread");
+ mainThreadField.setAccessible(true);
+ Object mainThread = mainThreadField.get(context);
+ //get ApplicationThread instance
+ Object applicationThread = mainThread.getClass().getMethod("getApplicationThread").invoke(mainThread);
+ //get Binder
+ Binder callerBinder = (Binder) (applicationThread.getClass().getMethod("asBinder").invoke(applicationThread));
+ */
+
+ //get handle
+// UserHandle userHandle = android.os.Process.myUserHandle();
+// int handle = (Integer) userHandle.getClass().getMethod("getIdentifier").invoke(userHandle);
+
+ //write pacel
+ mServiceData = Parcel.obtain();
+ mServiceData.writeInterfaceToken("android.app.IActivityManager");
+ mServiceData.writeStrongBinder(null);
+// mServiceData.writeStrongBinder(callerBinder);
+ intent.writeToParcel(mServiceData, 0);
+ mServiceData.writeString(null);
+// mServiceData.writeString(intent.resolveTypeIfNeeded(context.getContentResolver()));
+ mServiceData.writeInt(0);
+// mServiceData.writeInt(handle);
+
+ }
+
+ private boolean startServiceByAmsBinder(){
+ try {
+ if(mRemote == null || mServiceData == null){
+ Log.e("Daemon", "REMOTE IS NULL or PARCEL IS NULL !!!");
+ return false;
+ }
+ mRemote.transact(34, mServiceData, null, 0);//START_SERVICE_TRANSACTION = 34
+ return true;
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ return false;
+ }
+ }
+
+ private boolean installBinary(Context context){
+ String binaryDirName = null;
+// String abi = Build.CPU_ABI;
+// if (abi.startsWith("armeabi-v7a")) {
+// binaryDirName = "armeabi-v7a";
+// }else if(abi.startsWith("x86")) {
+// binaryDirName = "x86";
+// }else{
+// binaryDirName = "armeabi";
+// }
+ return install(context, BINARY_DEST_DIR_NAME, binaryDirName, BINARY_FILE_NAME);
+ }
+
+
+ private boolean install(Context context, String destDirName, String assetsDirName, String filename) {
+ File file = new File(context.getDir(destDirName, Context.MODE_PRIVATE), filename);
+ if (file.exists()) {
+ return true;
+ }
+ try {
+ copyAssets(context, (TextUtils.isEmpty(assetsDirName) ? "" : (assetsDirName + File.separator)) + filename, file, "700");
+ return true;
+ } catch (Exception e) {
+ return false;
+ }
+ }
+
+ private void copyAssets(Context context, String assetsFilename, File file, String mode) throws IOException, InterruptedException {
+ AssetManager manager = context.getAssets();
+ final InputStream is = manager.open(assetsFilename);
+ copyFile(file, is, mode);
+ }
+
+ private void copyFile(File file, InputStream is, String mode) throws IOException, InterruptedException {
+ if(!file.getParentFile().exists()){
+ file.getParentFile().mkdirs();
+ }
+ final String abspath = file.getAbsolutePath();
+ final FileOutputStream out = new FileOutputStream(file);
+ byte buf[] = new byte[1024];
+ int len;
+ while ((len = is.read(buf)) > 0) {
+ out.write(buf, 0, len);
+ }
+ out.close();
+ is.close();
+ Runtime.getRuntime().exec("chmod " + mode + " " + abspath).waitFor();
+ }
+
+}
View
3 LibMarsdaemon/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+<resources>
+ <string name="app_name">Marsdaemon</string>
+</resources>
View
15 LibMarsdaemon/src/test/java/com/marswin89/marsdaemon/ExampleUnitTest.java
@@ -0,0 +1,15 @@
+package com.marswin89.marsdaemon;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * To work on unit tests, switch the Test Artifact in the Build Variants view.
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() throws Exception {
+ assertEquals(4, 2 + 2);
+ }
+}
View
19 Marsdaemon2.iml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module external.linked.project.id="Marsdaemon2" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
+ <component name="FacetManager">
+ <facet type="java-gradle" name="Java-Gradle">
+ <configuration>
+ <option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/build" />
+ <option name="BUILDABLE" value="false" />
+ </configuration>
+ </facet>
+ </component>
+ <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="true">
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <excludeFolder url="file://$MODULE_DIR$/.gradle" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ </component>
+</module>
View
88 README.md
@@ -1,2 +1,88 @@
# MarsDaemon
-A light library, you can make your project depend it easily, and your project will be UNDEAD (contains api from 9 to 23, lol).
+
+It is a lite library, you can make your project depend it easily, and your project will be UNDEAD.
+
+ * support keeping alive from ADNROID_API 9 to ANDRIOD_API 23
+ * support keeping alive in most of devices(contains SUMSUNG\HUAWEI\MEIZU\MI\NEXUS..)
+ * support keeping alive in FORCE_CLOSE from SystemSettings and MEMORY_CLEAN from third-part apps (such like CleanMaster\360 and so on)
+ * surpports to keep BOOT_RECEIVER work well simplely
+
+
+### Version
+1.0
+
+## Installation
+#### STEP1
+make your project depend on LibMarsdaemon, and regist 2 Service and 2 BroadcastReceiver in your manifests in 2 different process.
+
+```sh
+<service android:name=".Service1" android:process=":process1"/>
+<receiver android:name=".Receiver1" android:process=":process1"/>
+<service android:name=".Service2" android:process=":process2"/>
+<receiver android:name=".Receiver2" android:process=":process2"/>
+```
+
+Service1 is the Service which you want to be undead, you can do somethings in it.
+
+But the others is used by Marsdaemon, so DONNOT do anything inside.
+
+#### STEP2
+make your application extends DaemonApplication and override the method getDaemonConfigurations(). Return back the confugirations.
+```sh
+@Override
+protected DaemonConfigurations getDaemonConfigurations() {
+ DaemonConfigurations.DaemonConfiguration configuration1 = new DaemonConfigurations.DaemonConfiguration("com.marswin89.marsdaemon.demo:process1", Service1.class.getCanonicalName(), Receiver1.class.getCanonicalName());
+ DaemonConfigurations.DaemonConfiguration configuration2 = new DaemonConfigurations.DaemonConfiguration("com.marswin89.marsdaemon.demo:process2", Service2.class.getCanonicalName(), Receiver2.class.getCanonicalName());
+ DaemonConfigurations.DaemonListener listener = new MyDaemonListener();
+ //return new DaemonConfigurations(configuration1, configuration2);//listener can be null
+ return new DaemonConfigurations(configuration1, configuration2, listener);
+}
+```
+if you want to override attachBaseContext you will find it had been defined final by me. you can override attachBaseContextByDaemon instead it.
+
+see more details in MyApplication1 in Demo
+
+##### if your application has extends another application, you should create a DaemonClient and perfrom it in attachBaseContext(), DONOT forget perform super.attachBaseContext() before!
+
+```sh
+private DaemonClient mDaemonClient;
+@Override
+protected void attachBaseContext(Context base) {
+ super.attachBaseContext(base);
+ mDaemonClient = new DaemonClient(createDaemonConfigurations());
+ mDaemonClient.onAttachBaseContext(base);
+}
+```
+see more details in MyApplication2 in DemoMarsdaemon
+
+#### STEP3
+Launch the Service once, and try to kill it.
+
+##
+##
+##
+## Contact me
+Email: Marswin89@gmail.com
+
+
+##
+##
+##
+
+License
+----
+
+Copyright (C) 2015, Mars Kwok
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
View
23 build.gradle
@@ -0,0 +1,23 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+ repositories {
+ jcenter()
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:1.3.0'
+
+ // NOTE: Do not place your application dependencies here; they belong
+ // in the individual module build.gradle files
+ }
+}
+
+allprojects {
+ repositories {
+ jcenter()
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
View
12 build/intermediates/dex-cache/cache.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<items version="2" >
+
+ <item
+ jar="/Users/guoyang/Workspace/workspace_github/Marsdaemon2/DemoMarsdaemon/build/intermediates/exploded-aar/Marsdaemon2/LibMarsdaemon/unspecified/jars/classes.jar"
+ jumboMode="false"
+ revision="23.0.2"
+ sha1="43b527e25decf1d24c3365c600eef0f5b01ba06e">
+ <dex dex="/Users/guoyang/Workspace/workspace_github/Marsdaemon2/DemoMarsdaemon/build/intermediates/pre-dexed/debug/classes-9e71f3a69a7a75f0e6ad61f439036846c69c2471.jar" />
+ </item>
+
+</items>
View
18 gradle.properties
@@ -0,0 +1,18 @@
+# Project-wide Gradle settings.
+
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+# Default value: -Xmx10248m -XX:MaxPermSize=256m
+# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
+
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
View
BIN gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
View
6 gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Wed Oct 21 11:34:03 PDT 2015
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.8-all.zip
View
160 gradlew
@@ -0,0 +1,160 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
View
90 gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
View
10 local.properties
@@ -0,0 +1,10 @@
+## This file is automatically generated by Android Studio.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file should *NOT* be checked into Version Control Systems,
+# as it contains information specific to your local configuration.
+#
+# Location of the SDK. This is only used by Gradle.
+# For customization when using a Version Control System, please read the
+# header note.
+sdk.dir=/Users/guoyang/Developer/android-sdk-macosx
View
1 settings.gradle
@@ -0,0 +1 @@
+include ':DemoMarsdaemon', ':LibMarsdaemon'

0 comments on commit 742759c

Please sign in to comment.
Something went wrong with that request. Please try again.