liuyuqi-dellpc 4 years ago
commit
8cef2b6955

+ 9 - 0
.classpath

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+	<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
+	<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="src" path="gen"/>
+	<classpathentry kind="output" path="bin/classes"/>
+</classpath>

+ 3 - 0
.gitignore

@@ -0,0 +1,3 @@
+/gen
+/bin
+/.settings

+ 33 - 0
.project

@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>StrongService</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>com.android.ide.eclipse.adt.ApkBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>

+ 28 - 0
AndroidManifest.xml

@@ -0,0 +1,28 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.servicetest2"
+    android:versionCode="1"
+    android:versionName="1.0" >
+
+    <uses-sdk
+        android:minSdkVersion="14"
+        android:targetSdkVersion="19" />
+
+    <application
+        android:allowBackup="true"
+        android:icon="@drawable/ic_launcher"
+        android:label="@string/app_name"
+        android:theme="@style/AppTheme" >
+        
+        <activity android:name="com.service.demo.Main">
+            <intent-filter >
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+        
+        <service android:enabled="true" android:name="com.service.demo.Service1" android:process=":service1"></service>
+        <service android:enabled="true" android:name="com.service.demo.Service2" android:process=":service2"></service>
+        
+    </application>
+
+</manifest>

BIN
ic_launcher-web.png


BIN
libs/android-support-v4.jar


+ 20 - 0
proguard-project.txt

@@ -0,0 +1,20 @@
+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# 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 *;
+#}

+ 14 - 0
project.properties

@@ -0,0 +1,14 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-21

BIN
res/drawable-hdpi/ic_launcher.png


BIN
res/drawable-mdpi/ic_launcher.png


BIN
res/drawable-xhdpi/ic_launcher.png


BIN
res/drawable-xxhdpi/ic_launcher.png


+ 19 - 0
res/layout/main.xml

@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical" >
+
+    <Button
+        android:id="@+id/button1"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="开启服务" />
+
+    <Button
+        android:id="@+id/button2"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="退出Activity" />
+
+</LinearLayout>

+ 11 - 0
res/values-v11/styles.xml

@@ -0,0 +1,11 @@
+<resources>
+
+    <!--
+        Base application theme for API 11+. This theme completely replaces
+        AppBaseTheme from res/values/styles.xml on API 11+ devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Holo.Light">
+        <!-- API 11 theme customizations can go here. -->
+    </style>
+
+</resources>

+ 12 - 0
res/values-v14/styles.xml

@@ -0,0 +1,12 @@
+<resources>
+
+    <!--
+        Base application theme for API 14+. This theme completely replaces
+        AppBaseTheme from BOTH res/values/styles.xml and
+        res/values-v11/styles.xml on API 14+ devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
+        <!-- API 14 theme customizations can go here. -->
+    </style>
+
+</resources>

+ 5 - 0
res/values/strings.xml

@@ -0,0 +1,5 @@
+<resources>
+
+    <string name="app_name">支持一键清理的双进程Service</string>
+
+</resources>

+ 20 - 0
res/values/styles.xml

@@ -0,0 +1,20 @@
+<resources>
+
+    <!--
+        Base application theme, dependent on API level. This theme is replaced
+        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Light">
+        <!--
+            Theme customizations available in newer API levels can go in
+            res/values-vXX/styles.xml, while customizations related to
+            backward-compatibility can go here.
+        -->
+    </style>
+
+    <!-- Application theme. -->
+    <style name="AppTheme" parent="AppBaseTheme">
+        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+    </style>
+
+</resources>

+ 64 - 0
src/com/service/demo/Main.java

@@ -0,0 +1,64 @@
+package com.service.demo;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+
+import com.example.servicetest2.R;
+/**
+ * Service双进程,一键清理后复活
+ * @author hellogv
+ *
+ */
+public class Main extends Activity implements OnClickListener {
+
+	private Button btn1,btn2;
+	//AIDL,此处用于bindService
+	private String TAG = getClass().getName();
+
+	@Override
+	protected void onCreate(Bundle savedInstanceState) {
+		// TODO Auto-generated method stub
+		super.onCreate(savedInstanceState);
+		setContentView(R.layout.main);
+		btn1 = (Button) findViewById(R.id.button1);
+		btn2 = (Button) findViewById(R.id.button2);
+		
+		btn1.setOnClickListener(this);
+		btn2.setOnClickListener(this);
+	
+	}
+	
+	@Override
+	protected void onDestroy() {
+		super.onDestroy();
+	}
+	
+	@Override
+	public void onClick(View v) {
+		switch (v.getId()) {
+		
+		case R.id.button1:
+			Intent i1 = new Intent(Main.this,Service1.class);
+			startService(i1);
+
+			Intent i2 = new Intent(Main.this,Service2.class);
+			startService(i2);
+			break;
+
+		case R.id.button2:
+			//关闭Activity
+			this.finish();
+			break;
+		}
+	}
+
+}

+ 89 - 0
src/com/service/demo/Service1.java

@@ -0,0 +1,89 @@
+package com.service.demo;
+
+import java.util.List;
+
+import android.app.ActivityManager;
+import android.app.ActivityManager.RunningAppProcessInfo;
+import android.app.Service;
+import android.app.ActivityManager.RunningServiceInfo;
+import android.content.ComponentCallbacks;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.res.Configuration;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+import android.widget.Toast;
+
+/**
+ * 
+ * @author hellogv
+ * 
+ */
+public class Service1 extends Service {
+
+	private String TAG = getClass().getName();
+	// 用于判断进程是否运行
+	private String Process_Name = "com.example.servicetest2:service2";
+
+	/**
+	 *启动Service2 
+	 */
+	private StrongService startS2 = new StrongService.Stub() {
+		@Override
+		public void stopService() throws RemoteException {
+			Intent i = new Intent(getBaseContext(), Service2.class);
+			getBaseContext().stopService(i);
+		}
+
+		@Override
+		public void startService() throws RemoteException {
+			Intent i = new Intent(getBaseContext(), Service2.class);
+			getBaseContext().startService(i);
+		}
+	};
+
+	@Override
+	public void onTrimMemory(int level){
+		Toast.makeText(getBaseContext(), "Service1 onTrimMemory..."+level, Toast.LENGTH_SHORT)
+		.show();
+		
+		keepService2();//保持Service2一直运行
+		
+	}
+
+	@Override
+	public void onCreate() {
+		Toast.makeText(Service1.this, "Service1 onCreate...", Toast.LENGTH_SHORT)
+				.show();
+		keepService2();
+	}
+
+	/**
+	 * 判断Service2是否还在运行,如果不是则启动Service2
+	 */
+	private  void keepService2(){
+		boolean isRun = Utils.isProessRunning(Service1.this, Process_Name);
+		if (isRun == false) {
+			try {
+				Toast.makeText(getBaseContext(), "重新启动 Service2", Toast.LENGTH_SHORT).show();
+				startS2.startService();
+			} catch (RemoteException e) {
+				e.printStackTrace();
+			}
+		}
+	}
+	
+	@Override
+	public int onStartCommand(Intent intent, int flags, int startId) {
+		return START_STICKY;
+	}
+
+	@Override
+	public IBinder onBind(Intent intent) {
+		return (IBinder) startS2;
+	}
+}

+ 81 - 0
src/com/service/demo/Service2.java

@@ -0,0 +1,81 @@
+package com.service.demo;
+
+import java.util.List;
+
+import android.app.ActivityManager;
+import android.app.ActivityManager.RunningAppProcessInfo;
+import android.app.ActivityManager.RunningServiceInfo;
+import android.app.Application;
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+import android.widget.Toast;
+/**
+ * 
+ * @author 掌缘生灭
+ *
+ */
+public class Service2 extends Service {
+	private String TAG = getClass().getName();
+	private String Process_Name = "com.example.servicetest2:service1";
+
+	/**
+	 *启动Service1 
+	 */
+	private StrongService startS1 = new StrongService.Stub() {
+
+		@Override
+		public void stopService() throws RemoteException {
+			Intent i = new Intent(getBaseContext(), Service1.class);
+			getBaseContext().stopService(i);
+		}
+
+		@Override
+		public void startService() throws RemoteException {
+			Intent i = new Intent(getBaseContext(), Service1.class);
+			getBaseContext().startService(i);
+			
+		}
+	};
+	
+	@Override
+	public void onTrimMemory(int level){
+		Toast.makeText(getBaseContext(), "Service2 onTrimMemory..."+level, Toast.LENGTH_SHORT)
+		.show();
+		keepService1();
+	}
+	
+	public void onCreate() {
+		Toast.makeText(Service2.this, "Service2 onCreate...", Toast.LENGTH_SHORT).show();
+		keepService1();
+	}
+
+	/**
+	 * 判断Service1是否还在运行,如果不是则启动Service1
+	 */
+	private  void keepService1(){
+		boolean isRun = Utils.isProessRunning(Service2.this, Process_Name);
+		if (isRun == false) {
+			try {
+				Toast.makeText(getBaseContext(), "重新启动 Service1", Toast.LENGTH_SHORT).show();
+				startS1.startService();
+			} catch (RemoteException e) {
+				e.printStackTrace();
+			}
+		}
+	}
+	@Override
+	public int onStartCommand(Intent intent, int flags, int startId) {
+		return START_STICKY;
+	}
+
+	@Override
+	public IBinder onBind(Intent intent) {
+		return (IBinder) startS1;
+	}
+
+}

+ 5 - 0
src/com/service/demo/StrongService.aidl

@@ -0,0 +1,5 @@
+package com.service.demo;
+interface StrongService{
+	void startService();
+	void stopService();
+}

+ 31 - 0
src/com/service/demo/Utils.java

@@ -0,0 +1,31 @@
+package com.service.demo;
+
+import java.util.List;
+
+import android.app.ActivityManager;
+import android.app.ActivityManager.RunningAppProcessInfo;
+import android.content.Context;
+
+public class Utils {
+
+	
+	/**
+	 * 判断进程是否运行
+	 * @return
+	 */
+	public static boolean isProessRunning(Context context, String proessName) {
+
+		boolean isRunning = false;
+		ActivityManager am = (ActivityManager) context
+				.getSystemService(Context.ACTIVITY_SERVICE);
+
+		List<RunningAppProcessInfo> lists = am.getRunningAppProcesses();
+		for (RunningAppProcessInfo info : lists) {
+			if (info.processName.equals(proessName)) {
+				isRunning = true;
+			}
+		}
+
+		return isRunning;
+	}
+}