lib补充文件提交

This commit is contained in:
2024-06-14 10:05:45 +08:00
parent b851dbc5ba
commit 9b2afe852e
85 changed files with 5481 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
/build
+39
View File
@@ -0,0 +1,39 @@
plugins {
id 'com.android.library'
id 'org.jetbrains.kotlin.android'
}
android {
compileSdk 33
defaultConfig {
minSdk 19
targetSdk 32
consumerProguardFiles 'consumer-rules.pro'
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
lint {
abortOnError false
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'androidx.annotation:annotation:1.6.0'
implementation 'androidx.core:core:1.10.1'
}
View File
+21
View File
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
+26
View File
@@ -0,0 +1,26 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.fanjun.keeplive">
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.REORDER_TASKS" />
<application>
<receiver android:name="com.fanjun.keeplive.receiver.NotificationClickReceiver" />
<activity
android:name="com.fanjun.keeplive.activity.OnePixelActivity"
android:excludeFromRecents="true"
android:launchMode="singleInstance"
android:theme="@style/onePixelActivity" />
<service android:name="com.fanjun.keeplive.service.LocalService" />
<service android:name="com.fanjun.keeplive.service.HideForegroundService" />
<service
android:name="com.fanjun.keeplive.service.JobHandlerService"
android:permission="android.permission.BIND_JOB_SERVICE" />
<service
android:name="com.fanjun.keeplive.service.RemoteService"
android:process=":remote" />
</application>
</manifest>
@@ -0,0 +1,6 @@
package com.fanjun.keeplive.service;
interface GuardAidl {
//相互唤醒服务
void wakeUp(String title, String discription, int iconRes);
}
@@ -0,0 +1,103 @@
package com.fanjun.keeplive;
import android.app.ActivityManager;
import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import androidx.annotation.NonNull;
import com.fanjun.keeplive.config.ForegroundNotification;
import com.fanjun.keeplive.config.KeepLiveService;
import com.fanjun.keeplive.service.JobHandlerService;
import com.fanjun.keeplive.service.LocalService;
import com.fanjun.keeplive.service.RemoteService;
import java.util.List;
/**
* 保活工具
*/
public final class KeepLive {
/**
* 运行模式
*/
public static enum RunMode {
/**
* 省电模式
* 省电一些,但保活效果会差一点
*/
ENERGY,
/**
* 流氓模式
* 相对耗电,但可造就不死之身
*/
ROGUE
}
public static ForegroundNotification foregroundNotification = null;
public static KeepLiveService keepLiveService = null;
public static RunMode runMode = null;
public static boolean useSilenceMusice = true;
/**
* 启动保活
*
* @param application your application
* @param foregroundNotification 前台服务 必须要,安卓8.0后必须有前台通知才能正常启动Service
* @param keepLiveService 保活业务
*/
public static void startWork(@NonNull Application application, @NonNull RunMode runMode, @NonNull ForegroundNotification foregroundNotification, @NonNull KeepLiveService keepLiveService) {
if (isMain(application)) {
KeepLive.foregroundNotification = foregroundNotification;
KeepLive.keepLiveService = keepLiveService;
KeepLive.runMode = runMode;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
//启动定时器,在定时器中启动本地服务和守护进程
Intent intent = new Intent(application, JobHandlerService.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
application.startForegroundService(intent);
} else {
application.startService(intent);
}
} else {
//启动本地服务
Intent localIntent = new Intent(application, LocalService.class);
//启动守护进程
Intent guardIntent = new Intent(application, RemoteService.class);
application.startService(localIntent);
application.startService(guardIntent);
}
}
}
/**
* 是否启用无声音乐
* 如不设置,则默认启用
* @param enable
*/
public static void useSilenceMusice(boolean enable){
KeepLive.useSilenceMusice = enable;
}
private static boolean isMain(Application application) {
int pid = android.os.Process.myPid();
String processName = "";
ActivityManager mActivityManager = (ActivityManager) application.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> runningAppProcessInfos = mActivityManager.getRunningAppProcesses();
if (runningAppProcessInfos != null) {
for (ActivityManager.RunningAppProcessInfo appProcess : mActivityManager.getRunningAppProcesses()) {
if (appProcess.pid == pid) {
processName = appProcess.processName;
break;
}
}
String packageName = application.getPackageName();
if (processName.equals(packageName)) {
return true;
}
}
return false;
}
}
@@ -0,0 +1,40 @@
package com.fanjun.keeplive.activity;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.os.PowerManager;
import android.view.Gravity;
import android.view.Window;
import android.view.WindowManager;
public final class OnePixelActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//设定一像素的activity
Window window = getWindow();
window.setGravity(Gravity.START | Gravity.TOP);
WindowManager.LayoutParams params = window.getAttributes();
params.x = 0;
params.y = 0;
params.height = 1;
params.width = 1;
window.setAttributes(params);
}
@Override
protected void onResume() {
super.onResume();
checkScreenOn("onResume");
}
private void checkScreenOn(String methodName) {
try{
PowerManager pm = (PowerManager) getApplicationContext().getSystemService(Context.POWER_SERVICE);
boolean isScreenOn = pm.isScreenOn();
if (isScreenOn) {
finish();
}
}catch (Exception e){}
}
}
@@ -0,0 +1,91 @@
package com.fanjun.keeplive.config;
import androidx.annotation.NonNull;
import java.io.Serializable;
/**
* 默认前台服务样式
*/
public class ForegroundNotification implements Serializable {
private String title;
private String description;
private int iconRes;
private ForegroundNotificationClickListener foregroundNotificationClickListener;
private ForegroundNotification(){
}
public ForegroundNotification(String title, String description, int iconRes, ForegroundNotificationClickListener foregroundNotificationClickListener) {
this.title = title;
this.description = description;
this.iconRes = iconRes;
this.foregroundNotificationClickListener = foregroundNotificationClickListener;
}
public ForegroundNotification(String title, String description, int iconRes) {
this.title = title;
this.description = description;
this.iconRes = iconRes;
}
/**
* 初始化
* @return ForegroundNotification
*/
public static ForegroundNotification ini(){
return new ForegroundNotification();
}
/**
* 设置标题
* @param title 标题
* @return ForegroundNotification
*/
public ForegroundNotification title(@NonNull String title){
this.title = title;
return this;
}
/**
* 设置副标题
* @param description 副标题
* @return ForegroundNotification
*/
public ForegroundNotification description(@NonNull String description){
this.description = description;
return this;
}
/**
* 设置图标
* @param iconRes 图标
* @return ForegroundNotification
*/
public ForegroundNotification icon(@NonNull int iconRes){
this.iconRes = iconRes;
return this;
}
/**
* 设置前台通知点击事件
* @param foregroundNotificationClickListener 前台通知点击回调
* @return ForegroundNotification
*/
public ForegroundNotification foregroundNotificationClickListener(@NonNull ForegroundNotificationClickListener foregroundNotificationClickListener){
this.foregroundNotificationClickListener = foregroundNotificationClickListener;
return this;
}
public String getTitle() {
return title==null?"":title;
}
public String getDescription() {
return description==null?"":description;
}
public int getIconRes() {
return iconRes;
}
public ForegroundNotificationClickListener getForegroundNotificationClickListener() {
return foregroundNotificationClickListener;
}
}
@@ -0,0 +1,11 @@
package com.fanjun.keeplive.config;
import android.content.Context;
import android.content.Intent;
/**
* 前台服务通知点击事件
*/
public interface ForegroundNotificationClickListener {
void foregroundNotificationClick(Context context, Intent intent);
}
@@ -0,0 +1,18 @@
package com.fanjun.keeplive.config;
/**
* 需要保活的服务
*/
public interface KeepLiveService {
/**
* 运行中
* 由于服务可能会多次自动启动,该方法可能重复调用
*/
void onWorking();
/**
* 服务终止
* 由于服务可能会被多次终止,该方法可能重复调用,需同onWorking配套使用,如注册和注销
*/
void onStop();
}
@@ -0,0 +1,102 @@
package com.fanjun.keeplive.config;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.os.Build;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.core.app.NotificationCompat;
public class NotificationUtils extends ContextWrapper {
private NotificationManager manager;
private String id;
private String name;
private Context context;
private NotificationChannel channel;
private NotificationUtils(Context context) {
super(context);
this.context = context;
id = context.getPackageName();
name = context.getPackageName();
}
@RequiresApi(api = Build.VERSION_CODES.O)
public void createNotificationChannel() {
if (channel == null) {
channel = new NotificationChannel(id, name, NotificationManager.IMPORTANCE_HIGH);
channel.enableVibration(false);
channel.enableLights(false);
channel.enableVibration(false);
channel.setVibrationPattern(new long[]{0});
channel.setSound(null, null);
getManager().createNotificationChannel(channel);
}
}
private NotificationManager getManager() {
if (manager == null) {
manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
}
return manager;
}
@RequiresApi(api = Build.VERSION_CODES.O)
public Notification.Builder getChannelNotification(String title, String content, int icon, Intent intent) {
//PendingIntent.FLAG_UPDATE_CURRENT 这个类型才能传值
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, getPendingIntent());
return new Notification.Builder(context, id)
.setContentTitle(title)
.setContentText(content)
.setSmallIcon(icon)
.setAutoCancel(true)
.setContentIntent(pendingIntent);
}
private int getPendingIntent() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.S ? PendingIntent.FLAG_IMMUTABLE : PendingIntent.FLAG_UPDATE_CURRENT;
}
public NotificationCompat.Builder getNotification_25(String title, String content, int icon, Intent intent) {
//PendingIntent.FLAG_UPDATE_CURRENT 这个类型才能传值
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, getPendingIntent());
return new NotificationCompat.Builder(context, id)
.setContentTitle(title)
.setContentText(content)
.setSmallIcon(icon)
.setAutoCancel(true)
.setVibrate(new long[]{0})
.setContentIntent(pendingIntent);
}
public static void sendNotification(@NonNull Context context, @NonNull String title, @NonNull String content, @NonNull int icon, @NonNull Intent intent) {
NotificationUtils notificationUtils = new NotificationUtils(context);
Notification notification = null;
if (Build.VERSION.SDK_INT >= 26) {
notificationUtils.createNotificationChannel();
notification = notificationUtils.getChannelNotification(title, content, icon, intent).build();
} else {
notification = notificationUtils.getNotification_25(title, content, icon, intent).build();
}
notificationUtils.getManager().notify(new java.util.Random().nextInt(10000), notification);
}
public static Notification createNotification(@NonNull Context context, @NonNull String title, @NonNull String content, @NonNull int icon, @NonNull Intent intent) {
NotificationUtils notificationUtils = new NotificationUtils(context);
Notification notification = null;
if (Build.VERSION.SDK_INT >= 26) {
notificationUtils.createNotificationChannel();
notification = notificationUtils.getChannelNotification(title, content, icon,intent).build();
} else {
notification = notificationUtils.getNotification_25(title, content, icon,intent).build();
}
return notification;
}
}
@@ -0,0 +1,22 @@
package com.fanjun.keeplive.receiver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import com.fanjun.keeplive.KeepLive;
public final class NotificationClickReceiver extends BroadcastReceiver {
public final static String CLICK_NOTIFICATION = "CLICK_NOTIFICATION";
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(NotificationClickReceiver.CLICK_NOTIFICATION)) {
if (KeepLive.foregroundNotification != null) {
if (KeepLive.foregroundNotification.getForegroundNotificationClickListener() != null) {
KeepLive.foregroundNotification.getForegroundNotificationClickListener().foregroundNotificationClick(context, intent);
}
}
}
}
}
@@ -0,0 +1,48 @@
package com.fanjun.keeplive.receiver;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Looper;
import com.fanjun.keeplive.activity.OnePixelActivity;
public final class OnepxReceiver extends BroadcastReceiver {
android.os.Handler mHander;
boolean screenOn = true;
public OnepxReceiver() {
mHander = new android.os.Handler(Looper.getMainLooper());
}
@Override
public void onReceive(final Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) { //屏幕关闭的时候接受到广播
screenOn = false;
mHander.postDelayed(new Runnable() {
@Override
public void run() {
if(!screenOn){
Intent intent2 = new Intent(context, OnePixelActivity.class);
intent2.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent2.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent2, 0);
try {
pendingIntent.send();
/*} catch (PendingIntent.CanceledException e) {*/
} catch (Exception e) {
e.printStackTrace();
}
}
}
},1000);
//通知屏幕已关闭,开始播放无声音乐
context.sendBroadcast(new Intent("_ACTION_SCREEN_OFF"));
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) { //屏幕打开的时候发送广播 结束一像素
screenOn = true;
//通知屏幕已点亮,停止播放无声音乐
context.sendBroadcast(new Intent("_ACTION_SCREEN_ON"));
}
}
}
@@ -0,0 +1,48 @@
package com.fanjun.keeplive.service;
import android.app.Notification;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import com.fanjun.keeplive.KeepLive;
import com.fanjun.keeplive.config.NotificationUtils;
import com.fanjun.keeplive.receiver.NotificationClickReceiver;
/**
* 隐藏前台服务通知
*/
public class HideForegroundService extends Service {
private android.os.Handler handler;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
startForeground();
if (handler == null){
handler = new Handler();
}
handler.postDelayed(new Runnable() {
@Override
public void run() {
stopForeground(true);
stopSelf();
}
}, 2000);
return START_NOT_STICKY;
}
private void startForeground() {
if (KeepLive.foregroundNotification != null) {
Intent intent = new Intent(getApplicationContext(), NotificationClickReceiver.class);
intent.setAction(NotificationClickReceiver.CLICK_NOTIFICATION);
Notification notification = NotificationUtils.createNotification(this, KeepLive.foregroundNotification.getTitle(), KeepLive.foregroundNotification.getDescription(), KeepLive.foregroundNotification.getIconRes(), intent);
startForeground(13691, notification);
}
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
@@ -0,0 +1,88 @@
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package com.fanjun.keeplive.service;
import android.app.Notification;
import android.app.job.JobParameters;
import android.app.job.JobScheduler;
import android.app.job.JobService;
import android.app.job.JobInfo.Builder;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Build.VERSION;
import androidx.annotation.RequiresApi;
import com.fanjun.keeplive.KeepLive;
import com.fanjun.keeplive.config.NotificationUtils;
import com.fanjun.keeplive.receiver.NotificationClickReceiver;
import com.fanjun.keeplive.utils.ServiceUtils;
@RequiresApi(
api = 21
)
public final class JobHandlerService extends JobService {
private JobScheduler mJobScheduler;
private int jobId = 100;
public JobHandlerService() {
}
public int onStartCommand(Intent intent, int flags, int startId) {
this.startService(this);
if (VERSION.SDK_INT >= 21) {
this.mJobScheduler = (JobScheduler) this.getSystemService("jobscheduler");
this.mJobScheduler.cancel(this.jobId);
Builder builder = new Builder(this.jobId, new ComponentName(this.getPackageName(), JobHandlerService.class.getName()));
if (VERSION.SDK_INT >= 24) {
builder.setMinimumLatency(30000L);
builder.setOverrideDeadline(30000L);
builder.setMinimumLatency(30000L);
builder.setBackoffCriteria(30000L, 0);
} else {
builder.setPeriodic(30000L);
}
builder.setRequiredNetworkType(1);
builder.setPersisted(true);
this.mJobScheduler.schedule(builder.build());
}
return 1;
}
private void startService(Context context) {
Intent localIntent;
if (VERSION.SDK_INT >= 26 && KeepLive.foregroundNotification != null) {
localIntent = new Intent(this.getApplicationContext(), NotificationClickReceiver.class);
localIntent.setAction("CLICK_NOTIFICATION");
Notification notification = NotificationUtils.createNotification(this, KeepLive.foregroundNotification.getTitle(), KeepLive.foregroundNotification.getDescription(), KeepLive.foregroundNotification.getIconRes(), localIntent);
this.startForeground(13691, notification);
}
localIntent = new Intent(context, LocalService.class);
Intent guardIntent = new Intent(context, RemoteService.class);
this.startService(localIntent);
this.startService(guardIntent);
}
public boolean onStartJob(JobParameters jobParameters) {
if (!ServiceUtils.isServiceRunning(this.getApplicationContext(), "com.fanjun.keeplive.service.LocalService") || !ServiceUtils.isRunningTaskExist(this.getApplicationContext(), this.getPackageName() + ":remote")) {
this.startService(this);
}
return false;
}
public boolean onStopJob(JobParameters jobParameters) {
if (!ServiceUtils.isServiceRunning(this.getApplicationContext(), "com.fanjun.keeplive.service.LocalService") || !ServiceUtils.isRunningTaskExist(this.getApplicationContext(), this.getPackageName() + ":remote")) {
this.startService(this);
}
return false;
}
}
@@ -0,0 +1,220 @@
package com.fanjun.keeplive.service;
import android.app.Notification;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.media.MediaPlayer;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.PowerManager;
import android.os.RemoteException;
import com.fanjun.keeplive.KeepLive;
import com.fanjun.keeplive.R;
import com.fanjun.keeplive.config.NotificationUtils;
import com.fanjun.keeplive.receiver.NotificationClickReceiver;
import com.fanjun.keeplive.receiver.OnepxReceiver;
import com.fanjun.keeplive.utils.ServiceUtils;
public final class LocalService extends Service {
private OnepxReceiver mOnepxReceiver;
private ScreenStateReceiver screenStateReceiver;
private boolean isPause = true;//控制暂停
private MediaPlayer mediaPlayer;
private MyBilder mBilder;
private android.os.Handler handler;
private boolean mIsBoundRemoteService ;
@Override
public void onCreate() {
super.onCreate();
if (mBilder == null) {
mBilder = new MyBilder();
}
PowerManager pm = (PowerManager) getApplicationContext().getSystemService(Context.POWER_SERVICE);
isPause = pm.isScreenOn();
if (handler == null) {
handler = new Handler();
}
}
@Override
public IBinder onBind(Intent intent) {
return mBilder;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (KeepLive.useSilenceMusice){
//播放无声音乐
if (mediaPlayer == null) {
mediaPlayer = MediaPlayer.create(this, R.raw.novioce);
if (mediaPlayer!= null){
mediaPlayer.setVolume(0f, 0f);
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mediaPlayer) {
if (!isPause) {
if (KeepLive.runMode == KeepLive.RunMode.ROGUE) {
play();
} else {
if (handler != null) {
handler.postDelayed(new Runnable() {
@Override
public void run() {
play();
}
}, 5000);
}
}
}
}
});
mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
return false;
}
});
play();
}
}
}
//像素保活
if (mOnepxReceiver == null) {
mOnepxReceiver = new OnepxReceiver();
}
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("android.intent.action.SCREEN_OFF");
intentFilter.addAction("android.intent.action.SCREEN_ON");
registerReceiver(mOnepxReceiver, intentFilter);
//屏幕点亮状态监听,用于单独控制音乐播放
if (screenStateReceiver == null) {
screenStateReceiver = new ScreenStateReceiver();
}
IntentFilter intentFilter2 = new IntentFilter();
intentFilter2.addAction("_ACTION_SCREEN_OFF");
intentFilter2.addAction("_ACTION_SCREEN_ON");
registerReceiver(screenStateReceiver, intentFilter2);
//启用前台服务,提升优先级
if (KeepLive.foregroundNotification != null) {
Intent intent2 = new Intent(getApplicationContext(), NotificationClickReceiver.class);
intent2.setAction(NotificationClickReceiver.CLICK_NOTIFICATION);
Notification notification = NotificationUtils.createNotification(this, KeepLive.foregroundNotification.getTitle(), KeepLive.foregroundNotification.getDescription(), KeepLive.foregroundNotification.getIconRes(), intent2);
startForeground(13691, notification);
}
//绑定守护进程
try {
Intent intent3 = new Intent(this, RemoteService.class);
mIsBoundRemoteService = this.bindService(intent3, connection, Context.BIND_ABOVE_CLIENT);
} catch (Exception e) {
}
//隐藏服务通知
try {
if(Build.VERSION.SDK_INT < 25){
startService(new Intent(this, HideForegroundService.class));
}
} catch (Exception e) {
}
if (KeepLive.keepLiveService != null) {
KeepLive.keepLiveService.onWorking();
}
return START_STICKY;
}
private void play() {
if (KeepLive.useSilenceMusice){
if (mediaPlayer != null && !mediaPlayer.isPlaying()) {
mediaPlayer.start();
}
}
}
private void pause() {
if (KeepLive.useSilenceMusice){
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
mediaPlayer.pause();
}
}
}
private class ScreenStateReceiver extends BroadcastReceiver {
@Override
public void onReceive(final Context context, Intent intent) {
if (intent.getAction().equals("_ACTION_SCREEN_OFF")) {
isPause = false;
play();
} else if (intent.getAction().equals("_ACTION_SCREEN_ON")) {
isPause = true;
pause();
}
}
}
private final class MyBilder extends GuardAidl.Stub {
@Override
public void wakeUp(String title, String discription, int iconRes) throws RemoteException {
}
}
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
if (ServiceUtils.isServiceRunning(getApplicationContext(), "com.fanjun.keeplive.service.LocalService")){
Intent remoteService = new Intent(LocalService.this,
RemoteService.class);
LocalService.this.startService(remoteService);
Intent intent = new Intent(LocalService.this, RemoteService.class);
mIsBoundRemoteService = LocalService.this.bindService(intent, connection,
Context.BIND_ABOVE_CLIENT);
}
PowerManager pm = (PowerManager) getApplicationContext().getSystemService(Context.POWER_SERVICE);
boolean isScreenOn = pm.isScreenOn();
if (isScreenOn) {
sendBroadcast(new Intent("_ACTION_SCREEN_ON"));
} else {
sendBroadcast(new Intent("_ACTION_SCREEN_OFF"));
}
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
try {
if (mBilder != null && KeepLive.foregroundNotification != null) {
GuardAidl guardAidl = GuardAidl.Stub.asInterface(service);
guardAidl.wakeUp(KeepLive.foregroundNotification.getTitle(), KeepLive.foregroundNotification.getDescription(), KeepLive.foregroundNotification.getIconRes());
}
} catch (RemoteException e) {
e.printStackTrace();
}
}
};
@Override
public void onDestroy() {
super.onDestroy();
if (connection != null){
try {
if (mIsBoundRemoteService){
unbindService(connection);
}
}catch (Exception e){}
}
try {
unregisterReceiver(mOnepxReceiver);
unregisterReceiver(screenStateReceiver);
}catch (Exception e){}
if (KeepLive.keepLiveService != null) {
KeepLive.keepLiveService.onStop();
}
}
}
@@ -0,0 +1,98 @@
package com.fanjun.keeplive.service;
import android.app.Notification;
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Build;
import android.os.IBinder;
import android.os.PowerManager;
import android.os.RemoteException;
import com.fanjun.keeplive.config.NotificationUtils;
import com.fanjun.keeplive.receiver.NotificationClickReceiver;
import com.fanjun.keeplive.utils.ServiceUtils;
/**
* 守护进程
*/
@SuppressWarnings(value={"unchecked", "deprecation"})
public final class RemoteService extends Service {
private MyBilder mBilder;
private boolean mIsBoundLocalService ;
@Override
public void onCreate() {
super.onCreate();
if (mBilder == null){
mBilder = new MyBilder();
}
}
@Override
public IBinder onBind(Intent intent) {
return mBilder;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
try {
mIsBoundLocalService = this.bindService(new Intent(RemoteService.this, LocalService.class),
connection, Context.BIND_ABOVE_CLIENT);
}catch (Exception e){
}
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
if (connection != null){
try {
if (mIsBoundLocalService){
unbindService(connection);
}
}catch (Exception e){}
}
}
private final class MyBilder extends GuardAidl.Stub {
@Override
public void wakeUp(String title, String discription, int iconRes) throws RemoteException {
if(Build.VERSION.SDK_INT < 25){
Intent intent2 = new Intent(getApplicationContext(), NotificationClickReceiver.class);
intent2.setAction(NotificationClickReceiver.CLICK_NOTIFICATION);
Notification notification = NotificationUtils.createNotification(RemoteService.this, title, discription, iconRes, intent2);
RemoteService.this.startForeground(13691, notification);
}
}
}
private final ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
if (ServiceUtils.isRunningTaskExist(getApplicationContext(), getPackageName() + ":remote")){
Intent localService = new Intent(RemoteService.this,
LocalService.class);
RemoteService.this.startService(localService);
mIsBoundLocalService = RemoteService.this.bindService(new Intent(RemoteService.this,
LocalService.class), connection, Context.BIND_ABOVE_CLIENT);
}
PowerManager pm = (PowerManager) RemoteService.this.getSystemService(Context.POWER_SERVICE);
boolean isScreenOn = pm.isScreenOn();
if (isScreenOn){
sendBroadcast(new Intent("_ACTION_SCREEN_ON"));
}else{
sendBroadcast(new Intent("_ACTION_SCREEN_OFF"));
}
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
}
};
}
@@ -0,0 +1,39 @@
package com.fanjun.keeplive.utils;
import android.app.ActivityManager;
import android.content.Context;
import java.util.Iterator;
import java.util.List;
public class ServiceUtils {
public static boolean isServiceRunning(Context ctx, String className) {
boolean isRunning = false;
ActivityManager activityManager = (ActivityManager) ctx
.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningServiceInfo> servicesList = activityManager
.getRunningServices(Integer.MAX_VALUE);
if (servicesList != null) {
Iterator<ActivityManager.RunningServiceInfo> l = servicesList.iterator();
while (l.hasNext()) {
ActivityManager.RunningServiceInfo si = l.next();
if (className.equals(si.service.getClassName())) {
isRunning = true;
}
}
}
return isRunning;
}
public static boolean isRunningTaskExist(Context context, String processName) {
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> processList = am.getRunningAppProcesses();
if (processList != null){
for (ActivityManager.RunningAppProcessInfo info : processList) {
if (info.processName.equals(processName)) {
return true;
}
}
}
return false;
}
}
Binary file not shown.
@@ -0,0 +1,2 @@
<resources>
</resources>
@@ -0,0 +1,9 @@
<resources>
<!--1像素保活透明Activity-->
<style name="onePixelActivity">
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item>
</style>
</resources>