@@ -55,3 +55,12 @@ buck-out/ | |||||
# Bundle artifact | # Bundle artifact | ||||
*.jsbundle | *.jsbundle | ||||
/yarn.lock | /yarn.lock | ||||
android/app/.classpath | |||||
android/app/.project | |||||
android/.project | |||||
android/.settings/* | |||||
android/app/.settings/* | |||||
android/app/src/main/gen/* | |||||
@@ -1,17 +0,0 @@ | |||||
<?xml version="1.0" encoding="UTF-8"?> | |||||
<projectDescription> | |||||
<name>screenAd</name> | |||||
<comment>Project android created by Buildship.</comment> | |||||
<projects> | |||||
</projects> | |||||
<buildSpec> | |||||
<buildCommand> | |||||
<name>org.eclipse.buildship.core.gradleprojectbuilder</name> | |||||
<arguments> | |||||
</arguments> | |||||
</buildCommand> | |||||
</buildSpec> | |||||
<natures> | |||||
<nature>org.eclipse.buildship.core.gradleprojectnature</nature> | |||||
</natures> | |||||
</projectDescription> |
@@ -1,2 +0,0 @@ | |||||
connection.project.dir= | |||||
eclipse.preferences.version=1 |
@@ -1,6 +0,0 @@ | |||||
<?xml version="1.0" encoding="UTF-8"?> | |||||
<classpath> | |||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8/"/> | |||||
<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer"/> | |||||
<classpathentry kind="output" path="bin/default"/> | |||||
</classpath> |
@@ -1,23 +0,0 @@ | |||||
<?xml version="1.0" encoding="UTF-8"?> | |||||
<projectDescription> | |||||
<name>app</name> | |||||
<comment>Project app created by Buildship.</comment> | |||||
<projects> | |||||
</projects> | |||||
<buildSpec> | |||||
<buildCommand> | |||||
<name>org.eclipse.jdt.core.javabuilder</name> | |||||
<arguments> | |||||
</arguments> | |||||
</buildCommand> | |||||
<buildCommand> | |||||
<name>org.eclipse.buildship.core.gradleprojectbuilder</name> | |||||
<arguments> | |||||
</arguments> | |||||
</buildCommand> | |||||
</buildSpec> | |||||
<natures> | |||||
<nature>org.eclipse.jdt.core.javanature</nature> | |||||
<nature>org.eclipse.buildship.core.gradleprojectnature</nature> | |||||
</natures> | |||||
</projectDescription> |
@@ -1,2 +0,0 @@ | |||||
connection.project.dir=.. | |||||
eclipse.preferences.version=1 |
@@ -5,7 +5,7 @@ | |||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/> | <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/> | ||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> | <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> | ||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> | <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> | ||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> | |||||
<application | <application | ||||
android:name=".MainApplication" | android:name=".MainApplication" | ||||
android:label="@string/app_name" | android:label="@string/app_name" | ||||
@@ -27,6 +27,10 @@ | |||||
</intent-filter> | </intent-filter> | ||||
</activity> | </activity> | ||||
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" /> | <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" /> | ||||
<service | |||||
android:name=".DaemonService" | |||||
android:exported="true" | |||||
android:launchMode="singleInstance" /> | |||||
<receiver android:name=".AutoStartBroadcastReceiver" > | <receiver android:name=".AutoStartBroadcastReceiver" > | ||||
<intent-filter> | <intent-filter> | ||||
<action android:name="android.intent.action.BOOT_COMPLETED" /> | <action android:name="android.intent.action.BOOT_COMPLETED" /> | ||||
@@ -1,8 +0,0 @@ | |||||
/*___Generated_by_IDEA___*/ | |||||
package com.screenad; | |||||
/* This stub is only used by the IDE. It is NOT the BuildConfig class actually packed into the APK */ | |||||
public final class BuildConfig { | |||||
public final static boolean DEBUG = Boolean.parseBoolean(null); | |||||
} |
@@ -1,7 +0,0 @@ | |||||
/*___Generated_by_IDEA___*/ | |||||
package com.screenad; | |||||
/* This stub is only used by the IDE. It is NOT the Manifest class actually packed into the APK */ | |||||
public final class Manifest { | |||||
} |
@@ -1,7 +0,0 @@ | |||||
/*___Generated_by_IDEA___*/ | |||||
package com.screenad; | |||||
/* This stub is only used by the IDE. It is NOT the R class actually packed into the APK */ | |||||
public final class R { | |||||
} |
@@ -0,0 +1,153 @@ | |||||
package com.screenad; | |||||
import android.app.Notification; | |||||
import android.app.NotificationManager; | |||||
import android.app.NotificationChannel; | |||||
import android.app.Service; | |||||
import android.content.Intent; | |||||
import android.os.Build; | |||||
import android.os.IBinder; | |||||
import android.app.ActivityManager; | |||||
import android.content.Context; | |||||
import android.content.pm.PackageInfo; | |||||
import android.content.pm.PackageManager; | |||||
import android.util.Log; | |||||
import java.util.concurrent.ExecutorService; | |||||
import java.util.concurrent.Executors; | |||||
import java.util.ArrayList; | |||||
import java.util.List; | |||||
import com.screenad.MainApplication; | |||||
import it.sauronsoftware.cron4j.Scheduler; | |||||
/** | |||||
* 守护进程,同时用来升级程序 | |||||
*/ | |||||
public class DaemonService extends Service { | |||||
// 核心进程 Service ID | |||||
private final static int CORE_SERVICE_ID = -5122; | |||||
private ExecutorService executorService = Executors.newSingleThreadExecutor(); | |||||
Scheduler scheduler; | |||||
public DaemonService() { | |||||
} | |||||
private static void log(String text) { | |||||
Log.i("DaemonService",text); | |||||
} | |||||
@Override | |||||
public void onCreate() { | |||||
super.onCreate(); | |||||
log("created"); | |||||
//利用 Android 漏洞提高进程优先级, 前台进程 | |||||
String CHANNEL_ONE_ID = "CHANNEL_ONE_ID"; | |||||
String CHANNEL_ONE_NAME= "CHANNEL_ONE_ID"; | |||||
NotificationChannel notificationChannel= null; | |||||
//进行8.0的判断 | |||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { | |||||
notificationChannel= new NotificationChannel(CHANNEL_ONE_ID, | |||||
CHANNEL_ONE_NAME, NotificationManager.IMPORTANCE_HIGH); | |||||
notificationChannel.setShowBadge(true); | |||||
notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC); | |||||
NotificationManager manager= (NotificationManager) getSystemService(NOTIFICATION_SERVICE); | |||||
manager.createNotificationChannel(notificationChannel); | |||||
} | |||||
Notification notification= new Notification.Builder(this).setChannelId(CHANNEL_ONE_ID) | |||||
.setContentTitle("DaemonService") | |||||
.build(); | |||||
notification.flags|= Notification.FLAG_NO_CLEAR; | |||||
startForeground(CORE_SERVICE_ID, notification); | |||||
} | |||||
@Override | |||||
public int onStartCommand(Intent intent, int flags, int startId) { | |||||
log("started"); | |||||
executorService.submit(new Runnable() { | |||||
@Override | |||||
public void run() { | |||||
startCronTabTask(); | |||||
} | |||||
}); | |||||
return START_STICKY; | |||||
} | |||||
private boolean isProcessWork(Context context, String processName) { | |||||
ActivityManager myAM = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); | |||||
List<ActivityManager.RunningAppProcessInfo> processInfos = myAM.getRunningAppProcesses(); | |||||
if (processInfos == null) { | |||||
return false; | |||||
} | |||||
for (ActivityManager.RunningAppProcessInfo processInfo : processInfos) { | |||||
if (processInfo.processName.equals(processName)) { | |||||
return true; | |||||
} | |||||
} | |||||
return false; | |||||
} | |||||
private boolean isBackground(Context context, String packageName) { | |||||
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); | |||||
List<ActivityManager.RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses(); | |||||
for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) { | |||||
if (appProcess.processName.equals(packageName)) { | |||||
/* BACKGROUND=400 EMPTY=500 FOREGROUND=100 GONE=1000 PERCEPTIBLE=130 SERVICE=300 ISIBLE=200 */ | |||||
log(ppProcess.processName + " appimportace =" + appProcess.importance); | |||||
if (appProcess.importance != ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) { | |||||
log("处于后台" + appProcess.processName); | |||||
return true; | |||||
} else { | |||||
log("处于前台" + appProcess.processName); | |||||
return false; | |||||
} | |||||
} | |||||
} | |||||
return false; | |||||
} | |||||
/** | |||||
* 开启cron4jtab定时任务 | |||||
*/ | |||||
private void startCronTabTask() { | |||||
if (scheduler != null) { | |||||
scheduler.stop(); | |||||
} | |||||
scheduler = new Scheduler(); | |||||
scheduler.isDaemon(); | |||||
scheduler.schedule("* * * * *", new Runnable() { | |||||
public void run() { | |||||
try { | |||||
if (!isProcessWork(MainApplication.getContext(), "com.screenad") || | |||||
isBackground(MainApplication.getContext(), "com.screenad")) { | |||||
log("正在重启 com.screenad..."); | |||||
Intent newIntent = MainApplication.getContext().getPackageManager().getLaunchIntentForPackage("com.screenad"); | |||||
MainApplication.getContext().startActivity(newIntent); | |||||
}else{ | |||||
log("运行良好 com.screenad..."); | |||||
} | |||||
} catch (Exception e) { | |||||
log(e.getMessage()); | |||||
} | |||||
} | |||||
}); | |||||
scheduler.start(); | |||||
} | |||||
@Override | |||||
public IBinder onBind(Intent intent) { | |||||
throw new UnsupportedOperationException("Not yet implemented"); | |||||
} | |||||
@Override | |||||
public void onDestroy() { | |||||
super.onDestroy(); | |||||
} | |||||
} |
@@ -1,7 +1,9 @@ | |||||
package com.screenad; | package com.screenad; | ||||
import com.screenad.DaemonService; | |||||
import android.app.Application; | import android.app.Application; | ||||
import android.content.Context; | |||||
import android.content.Intent; | |||||
import com.facebook.react.ReactApplication; | import com.facebook.react.ReactApplication; | ||||
import com.horcrux.svg.SvgPackage; | import com.horcrux.svg.SvgPackage; | ||||
import org.reactnative.camera.RNCameraPackage; | import org.reactnative.camera.RNCameraPackage; | ||||
@@ -18,7 +20,7 @@ import com.facebook.soloader.SoLoader; | |||||
import java.util.Arrays; | import java.util.Arrays; | ||||
import java.util.List; | import java.util.List; | ||||
import android.util.Log; | |||||
public class MainApplication extends Application implements ReactApplication { | public class MainApplication extends Application implements ReactApplication { | ||||
@@ -57,6 +59,13 @@ public class MainApplication extends Application implements ReactApplication { | |||||
} | } | ||||
}; | }; | ||||
private static void log(String text) { | |||||
Log.i("MainApplication",text); | |||||
} | |||||
private static Context context; | |||||
public static Context getContext() { | |||||
return context; | |||||
} | |||||
@Override | @Override | ||||
public ReactNativeHost getReactNativeHost() { | public ReactNativeHost getReactNativeHost() { | ||||
return mReactNativeHost; | return mReactNativeHost; | ||||
@@ -65,6 +74,9 @@ public class MainApplication extends Application implements ReactApplication { | |||||
@Override | @Override | ||||
public void onCreate() { | public void onCreate() { | ||||
super.onCreate(); | super.onCreate(); | ||||
context = this; | |||||
SoLoader.init(this, /* native exopackage */ false); | SoLoader.init(this, /* native exopackage */ false); | ||||
context.startForegroundService(new Intent(getContext(), DaemonService.class)); | |||||
log("started"); | |||||
} | } | ||||
} | } |