diff --git a/app/build.gradle b/app/build.gradle
index fe4365a..aa5f03b 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -37,8 +37,8 @@ android {
applicationId "com.navinfo.outdoor"
minSdkVersion 24
targetSdkVersion 30
- versionCode 117
- versionName "8.231011-金山云测试版"
+ versionCode 118
+ versionName "8.231110-通用测试版"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
ndk {
@@ -230,6 +230,6 @@ dependencies {
implementation 'com.tencent.jg:jg:1.1'
//推送保活库
implementation 'com.github.xuexiangjys.XPush:keeplive:1.0.0'
- // Android应用白名单添加 https://github.com/WaseemSabir/BatteryPermissionHelper
- implementation 'com.waseemsabir:betterypermissionhelper:1.0.3'
+// // Android应用白名单添加 https://github.com/WaseemSabir/BatteryPermissionHelper
+// implementation 'com.waseemsabir:betterypermissionhelper:1.0.3'
}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 92bfda8..021f688 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -19,7 +19,7 @@
-
+
@@ -51,6 +51,8 @@
+
+
+
+
0) {
+ if (mTab.getSelectedTabPosition()!=0) {
+ mTab.getTabAt(0).select(); // 默认选中第一个选项
+ }
+ // 地图定位到指定位置,发送Event
+ Map map = new HashMap<>();
+ map.put("geom", geom);
+ map.put("zoom", zoom);
+ Message msg = Message.obtain();
+ msg.obj = map;
+ msg.what = Constant.EVENT_WHAT_NOTIFYCATION_RECOMMAND_TASK;
+ EventBus.getDefault().post(msg);
+ }
+ } else if (intentFrom.equals("normalNotification")) {
+ String title = intent.getStringExtra(Constant.NOTIFYCATION_TITLE);
+ String content = intent.getStringExtra(Constant.NOTIFYCATION_CONTENT);
+ if (title != null && content != null) {
+ // 显示对话框
+ MessageDialog.show(HomeActivity.this, title, content, "确定")
+ .setCancelable(false);
+ }
+ }
+ }
+ }
}
private void initUM() {
@@ -182,7 +232,7 @@ public class HomeActivity extends BaseActivity {
Log.i("TAGEE", "click dismissNotification: " + msg.getRaw().toString());
}
};
- UserApplication.instance.setNotificationClickHandler(notificationClickHandler);
+// UserApplication.instance.setNotificationClickHandler(notificationClickHandler);
}
@Override
diff --git a/app/src/main/java/com/navinfo/outdoor/api/Constant.java b/app/src/main/java/com/navinfo/outdoor/api/Constant.java
index 2c0c487..a096f1a 100644
--- a/app/src/main/java/com/navinfo/outdoor/api/Constant.java
+++ b/app/src/main/java/com/navinfo/outdoor/api/Constant.java
@@ -44,6 +44,7 @@ public class Constant {
public static String LOG_FOLDER = ROOT_FOLDER + "/log";
public static String GPS_LOG_FOLDER = ROOT_FOLDER + "/gps_log";
public static int TelLength = 0;
+ public static String PUSH_TOKEN = null;
public static Map mockGPSMap; // 是否模拟定位,如果模拟定位,该map不为空
public static void initRootFolder(String userId) {
@@ -156,6 +157,7 @@ public class Constant {
public static final int EVENT_WHAT_START_DRAW_LINE=63;// 开始绘制参考线
public static final int EVENT_WHAT_FINISH_DRAW_LINE=64;// 完成绘制参考线
public static final int SWITCH_RECORFER_ITEM=65;//记录界面请求数据提醒
+ public static final int EVENT_WHAT_NOTIFYCATION_RECOMMAND_TASK=66;//记录界面请求数据提醒
public static final String INTENT_POI_VIDEO_TYPE = "poi_video_type";
public static int NUMBER = 200; //任务个数
public static int LIMIT_TYPE = -1; //权限类型,普通任务-0,专属任务-1
@@ -282,4 +284,10 @@ public class Constant {
public static NAV_TYPE currentNaviType; // 当前的导航方式
public static boolean NAV_NEAREST_POI = false;
+
+ public static String NOTIFYCATION_INTENT_FROM = "NOTIFYCATION_INTENT_FROM";
+ public static String NOTIFYCATION_TASK_GEOM = "NOTIFYCATION_TASK_GEOM";
+ public static String NOTIFYCATION_TASK_ZOOM = "NOTIFYCATION_TASK_ZOOM";
+ public static String NOTIFYCATION_TITLE = "NOTIFYCATION_TITLE";
+ public static String NOTIFYCATION_CONTENT = "NOTIFYCATION_CONTENT";
}
diff --git a/app/src/main/java/com/navinfo/outdoor/api/UserApplication.java b/app/src/main/java/com/navinfo/outdoor/api/UserApplication.java
index b841cf3..d48fa05 100644
--- a/app/src/main/java/com/navinfo/outdoor/api/UserApplication.java
+++ b/app/src/main/java/com/navinfo/outdoor/api/UserApplication.java
@@ -29,12 +29,6 @@ import com.tencent.map.navi.TencentNavi;
import com.tencent.navi.surport.utils.DeviceUtils;
import com.tencent.tencentmap.mapsdk.maps.TencentMapInitializer;
import com.umeng.commonsdk.UMConfigure;
-import com.umeng.message.IUmengRegisterCallback;
-import com.umeng.message.MsgConstant;
-import com.umeng.message.PushAgent;
-import com.umeng.message.UmengMessageHandler;
-import com.umeng.message.UmengNotificationClickHandler;
-import com.umeng.message.entity.UMessage;
import com.umeng.umcrash.UMCrash;
import com.umeng.umcrash.UMCrashCallback;
@@ -50,7 +44,7 @@ import okhttp3.OkHttpClient;
public class UserApplication extends Application {
public static UserApplication userApplication;
public static ExecutorService fixedThreadPool;
- public static PushAgent instance;
+// public static PushAgent instance;
@Override
public void onCreate() {
@@ -80,7 +74,8 @@ public class UserApplication extends Application {
@Override
public void onSuccess(Object data, int flag) {
//token在设备卸载重装的时候有可能会变
- Log.d("TPush", "注册成功,设备token为:" + data);
+// Log.d("TPush", "注册成功,设备token为:" + data);
+ // 推送注册成功,将当前用户token上传给服务器
}
@@ -107,49 +102,49 @@ public class UserApplication extends Application {
return "注册友盟异常查看功能";
}
});
- instance = PushAgent.getInstance(this);
- instance.register(new IUmengRegisterCallback() {
- @Override
- public void onSuccess(String s) {
- //注册成功会返回deviceToken deviceToken是推送消息的唯一标志
- Constant.DEVICE_TOKEN = s;
- Log.i("TAGEE", "Success 注册成功:deviceToken:--> " + Constant.DEVICE_TOKEN);
- }
-
- @Override
- public void onFailure(String s, String s1) {
- Log.e("TAGEE", "Failure 注册失败:--> " + "code:" + s + ", desc:" + s1);
- }
- });
- instance.onAppStart();
- UmengMessageHandler msgHandler = new UmengMessageHandler() {
- //处理通知栏消息
- @Override
- public void dealWithNotificationMessage(Context context, UMessage msg) {
- super.dealWithNotificationMessage(context, msg);
- Log.i("TAGEE", "dealWithNotificationMessage:" + msg.getRaw().toString());
- Constant.NOTIFICATION=msg.getRaw().toString();
- }
-
- //自定义通知样式,此方法可以修改通知样式等
- @Override
- public Notification getNotification(Context context, UMessage msg) {
- Log.i("TAGEE", "getNotification: "+msg.getRaw().toString());
- return super.getNotification(context, msg);
- }
-
- //处理透传消息
- @Override
- public void dealWithCustomMessage(Context context, UMessage msg) {
- super.dealWithCustomMessage(context, msg);
- Log.i("TAGEE", "dealWithCustomMessage:" + msg.getRaw().toString());
- }
- };
- instance.setMessageHandler(msgHandler);
+// instance = PushAgent.getInstance(this);
+// instance.register(new IUmengRegisterCallback() {
+// @Override
+// public void onSuccess(String s) {
+// //注册成功会返回deviceToken deviceToken是推送消息的唯一标志
+// Constant.DEVICE_TOKEN = s;
+// Log.i("TAGEE", "Success 注册成功:deviceToken:--> " + Constant.DEVICE_TOKEN);
+// }
+//
+// @Override
+// public void onFailure(String s, String s1) {
+// Log.e("TAGEE", "Failure 注册失败:--> " + "code:" + s + ", desc:" + s1);
+// }
+// });
+// instance.onAppStart();
+// UmengMessageHandler msgHandler = new UmengMessageHandler() {
+// //处理通知栏消息
+// @Override
+// public void dealWithNotificationMessage(Context context, UMessage msg) {
+// super.dealWithNotificationMessage(context, msg);
+// Log.i("TAGEE", "dealWithNotificationMessage:" + msg.getRaw().toString());
+// Constant.NOTIFICATION=msg.getRaw().toString();
+// }
+//
+// //自定义通知样式,此方法可以修改通知样式等
+// @Override
+// public Notification getNotification(Context context, UMessage msg) {
+// Log.i("TAGEE", "getNotification: "+msg.getRaw().toString());
+// return super.getNotification(context, msg);
+// }
+//
+// //处理透传消息
+// @Override
+// public void dealWithCustomMessage(Context context, UMessage msg) {
+// super.dealWithCustomMessage(context, msg);
+// Log.i("TAGEE", "dealWithCustomMessage:" + msg.getRaw().toString());
+// }
+// };
+// instance.setMessageHandler(msgHandler);
//App处于前台时不显示通知
//instance.setNotificationOnForeground(false);
//设置显示通知的数量
- instance.setDisplayNotificationNumber(0);
+// instance.setDisplayNotificationNumber(0);
//服务端控制声音
//instance.setNotificationPlaySound(MsgConstant.NOTIFICATION_PLAY_SERVER);
//通知免打扰时段
diff --git a/app/src/main/java/com/navinfo/outdoor/fragment/TreasureFragment.java b/app/src/main/java/com/navinfo/outdoor/fragment/TreasureFragment.java
index 8d3c70b..55d0941 100644
--- a/app/src/main/java/com/navinfo/outdoor/fragment/TreasureFragment.java
+++ b/app/src/main/java/com/navinfo/outdoor/fragment/TreasureFragment.java
@@ -78,11 +78,13 @@ import com.navinfo.outdoor.http.OkGoBuilder;
import com.navinfo.outdoor.http.UploadCallBack;
import com.navinfo.outdoor.room.ChargingPileEntity;
import com.navinfo.outdoor.room.PoiEntity;
+import com.navinfo.outdoor.util.Base64;
import com.navinfo.outdoor.util.FlushTokenUtil;
import com.navinfo.outdoor.util.Geohash;
import com.navinfo.outdoor.util.GeometryTools;
import com.navinfo.outdoor.util.LocationLifeCycle;
import com.navinfo.outdoor.util.MapManager;
+import com.navinfo.outdoor.util.Md5Util;
import com.navinfo.outdoor.util.MyTecentLocationSource;
import com.navinfo.outdoor.util.NaviUtils;
import com.navinfo.outdoor.util.NetWorkUtils;
@@ -285,7 +287,7 @@ public class TreasureFragment extends BaseFragment implements View.OnClickListen
treasureBuilder.append(TimestampUtil.time()).append(",").append("onFinish-获取到当前位置,");
dismissLoadingDialog();
refreshFilterData();
- //上传用户位置金纬度
+ //上传用户位置经纬度
iniUserLocation();
//得到电话区号,电话位数
initPhone();
@@ -293,6 +295,8 @@ public class TreasureFragment extends BaseFragment implements View.OnClickListen
initUM();
//检查是否有没有填完的页面
initSharePre();
+ // 获取最新的推荐任务,如果存在则显示推荐任务按钮
+ initRecommandTaskInfo();
}
@Override
@@ -1180,6 +1184,32 @@ public class TreasureFragment extends BaseFragment implements View.OnClickListen
}
});
}
+ } else if (data.what == Constant.EVENT_WHAT_NOTIFYCATION_RECOMMAND_TASK) {
+ // 显示推荐任务
+ Map dataMap = (Map) data.obj;
+ String geom = dataMap.get("geom").toString();
+ Geometry geometry = GeometryTools.createGeometry(geom);
+ int zoom = Integer.parseInt(dataMap.get("zoom").toString());
+ // 跳转到该位置
+ // 地图中心点位置设置为当前用户所在位置
+ CameraUpdate cameraSigma =
+ CameraUpdateFactory.newCameraPosition(new CameraPosition(
+ new LatLng(geometry.getCoordinate().y, geometry.getCoordinate().x), //中心点坐标,地图目标经纬度
+ zoom, //目标缩放级别
+ 0, //目标倾斜角[0.0 ~ 45.0] (垂直地图时为0)
+ 0)); //目标旋转角 0~360° (正北方为0)
+ tencentMap.animateCamera(cameraSigma, new TencentMap.CancelableCallback() {
+ @Override
+ public void onFinish() {
+ // 重新刷新数据
+ refreshFilterData();
+ }
+
+ @Override
+ public void onCancel() {
+
+ }
+ });
}
}
@@ -2031,4 +2061,16 @@ public class TreasureFragment extends BaseFragment implements View.OnClickListen
removableHashMap.put(geo, markers);
}
}
+
+ /**
+ * 获取最新的推荐任务数据
+ * */
+ private void initRecommandTaskInfo() {
+ if (Constant.PUSH_TOKEN!=null) {
+ HttpParams httpParams = new HttpParams();
+ httpParams.put("pushId", Constant.PUSH_TOKEN);
+ long time = System.currentTimeMillis();
+ httpParams.put("datetime", time);
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/navinfo/outdoor/http/HttpInterface.java b/app/src/main/java/com/navinfo/outdoor/http/HttpInterface.java
index fb7cc7d..2fa6014 100644
--- a/app/src/main/java/com/navinfo/outdoor/http/HttpInterface.java
+++ b/app/src/main/java/com/navinfo/outdoor/http/HttpInterface.java
@@ -64,6 +64,7 @@ public class HttpInterface {
public static String EXAM_CONTENT = null;//发现 -能力测评获取试题接口
//172.23.139.4:8002/findAndMessage/1/submitExam
public static String EXAM_SUBMIT = null;//发现 -能力测评提交试卷 post
+ public static String RECOMMAND_TASK = null;//TreasureFragment获取最新的推荐任务信息 post
/* 登录
* Path=/m4/userlogin/
@@ -169,6 +170,7 @@ public class HttpInterface {
USER_DETAIL_BY_USER_ID = IP + USER_PATH + "user/" + userId + "/getUserDetailByUserid/" + userId; //获取用户信息
//172.21.98.90:9999/m4/user/userGuide/1/insertUserGuide
INSERT_USER_GUIDE = IP + USER_PATH + "userGuide/" + userId + "/insertUserGuide";//引导页完成接口
+ RECOMMAND_TASK = IP + USER_PATH + "user/" + userId + "/lastRecommandTask";//获取用户推荐信息
/* 发现
* Path=/m4/msgList/
diff --git a/app/src/main/java/com/navinfo/outdoor/receiver/MessageReceiver.java b/app/src/main/java/com/navinfo/outdoor/receiver/MessageReceiver.java
index 5ac12bd..439bfe9 100644
--- a/app/src/main/java/com/navinfo/outdoor/receiver/MessageReceiver.java
+++ b/app/src/main/java/com/navinfo/outdoor/receiver/MessageReceiver.java
@@ -1,11 +1,27 @@
package com.navinfo.outdoor.receiver;
+import android.Manifest;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.os.Build;
import android.util.Log;
import android.widget.Toast;
+import androidx.core.app.ActivityCompat;
+import androidx.core.app.NotificationCompat;
+import androidx.core.content.ContextCompat;
+
+import com.bumptech.glide.Glide;
import com.elvishew.xlog.XLog;
+import com.navinfo.outdoor.R;
+import com.navinfo.outdoor.activity.HomeActivity;
+import com.navinfo.outdoor.api.Constant;
import com.tencent.android.tpush.NotificationAction;
import com.tencent.android.tpush.XGPushBaseReceiver;
import com.tencent.android.tpush.XGPushClickedResult;
@@ -16,6 +32,10 @@ import com.tencent.android.tpush.XGPushTextMessage;
import org.json.JSONException;
import org.json.JSONObject;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
public class MessageReceiver extends XGPushBaseReceiver {
public static final String UPDATE_LISTVIEW_ACTION = "com.qq.xgdemo.activity.UPDATE_LISTVIEW";
public static final String TEST_ACTION = "com.qq.xgdemo.activity.TEST_ACTION";
@@ -28,25 +48,126 @@ public class MessageReceiver extends XGPushBaseReceiver {
*/
@Override
public void onTextMessage(Context context, XGPushTextMessage message) {
- String text = "onTextMessage:" + message.toString();
- // 获取自定义key-value
- String customContent = message.getCustomContent();
- if (customContent != null && customContent.length() != 0) {
- try {
- JSONObject obj = new JSONObject(customContent);
- // key1为前台配置的key
- if (!obj.isNull("key")) {
- String value = obj.getString("key");
- XLog.d("get custom value:" + value);
+// String text = "onTextMessage:" + message.toString();
+// // 获取自定义key-value
+// String customContent = message.getCustomContent();
+// if (customContent != null && customContent.length() != 0) {
+// try {
+// JSONObject obj = new JSONObject(customContent);
+// // key1为前台配置的key
+// if (!obj.isNull("key")) {
+// String value = obj.getString("key");
+// XLog.d("get custom value:" + value);
+// }
+// // ...
+// } catch (JSONException e) {
+// e.printStackTrace();
+// }
+// }
+// // APP自主处理消息的过程...
+// XLog.d(text);
+// show(context, text);
+
+ // 获取透传信息内容
+ String msgContent = message.getContent();
+ // 使用json解析msgContent
+ try {
+ JSONObject msgJson = new JSONObject(msgContent);
+ // 获取当前json的id,如果id大于等于0,则根据Content内容尝试展示提示信息
+ int id = msgJson.optInt("id", -1);
+ if (id >= 0) {
+ int type = msgJson.optInt("type", -1);
+ if (type == 0) { // 显示推荐任务
+ String imgUrl = msgJson.optString("img", "");
+ String wkt = msgJson.optString("geom", "");
+ int zoom = msgJson.optInt("zoom", 17);
+ // 获取推荐任务的大图
+ try {
+ Bitmap bigBitmap = Glide.with(context).asBitmap().load(imgUrl).submit().get(16000, TimeUnit.MILLISECONDS);
+ if (bigBitmap==null) {
+ bigBitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_launcher);
+ }
+ if (bigBitmap!=null) {
+ // 显示notifycation
+ createNotificationForBigImage(context,
+ msgJson.optString("title", "推荐任务"),
+ msgJson.optString("content", "为你准备的推荐任务"),
+ bigBitmap, wkt, zoom, id);
+ }
+ } catch (ExecutionException e) {
+ throw new RuntimeException(e);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ } catch (TimeoutException e) {
+ throw new RuntimeException(e);
+ }
+ } else if (type == 1) {
+ // 显示普通通知
+ String title = msgJson.optString("title", "通知");
+ String content = msgJson.optString("content", "");
+ // 展示普通notification
+ createNotificationForNormal(context, title, content, id);
}
- // ...
- } catch (JSONException e) {
- e.printStackTrace();
+ } else {
+ // id小于0,说明当前没有可推送的任务
+
}
+ } catch (JSONException e) {
+ throw new RuntimeException(e);
}
- // APP自主处理消息的过程...
- XLog.d(text);
- show(context, text);
+ }
+
+ private void createNotificationForNormal(Context context, String contentTitle, String contentText, int id) {
+ String mNormalChannelId = "normalNotification";
+ String mNormalChannelName = "普通通知";
+ NotificationManager mManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ NotificationChannel channel = new NotificationChannel(mNormalChannelId, mNormalChannelName, NotificationManager.IMPORTANCE_DEFAULT);
+ mManager.createNotificationChannel(channel);
+ }
+ Intent intent = new Intent(context, HomeActivity.class);
+ intent.putExtra(Constant.NOTIFYCATION_INTENT_FROM, "normalNotification");
+ intent.putExtra(Constant.NOTIFYCATION_TITLE, contentTitle);
+ intent.putExtra(Constant.NOTIFYCATION_CONTENT, contentText);
+ PendingIntent pendingIntent = PendingIntent.getActivity(context, id, intent, PendingIntent.FLAG_CANCEL_CURRENT);
+ NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context, mNormalChannelId)
+ .setContentTitle(contentTitle)
+ .setContentText(contentText)
+ .setStyle(new NotificationCompat.BigTextStyle().bigText(contentText))
+ .setSmallIcon(R.mipmap.ic_launcher)
+ .setSilent(false)
+ .setAutoCancel(true)
+ .setContentIntent(pendingIntent)
+ .addAction(R.mipmap.ic_launcher, "去看看", pendingIntent);
+ mManager.notify(2, mBuilder.build());
+ }
+
+ private void createNotificationForBigImage(Context context, String contentTitle, String contentText, Bitmap bigPic,
+ String wkt, int zoom, int id) {
+ String mBigImageChannelId = "recommendTaskId";
+ String mBigImageChannelName = "推荐任务";
+ NotificationManager mManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ NotificationChannel channel = new NotificationChannel(mBigImageChannelId, mBigImageChannelName, NotificationManager.IMPORTANCE_DEFAULT);
+ mManager.createNotificationChannel(channel);
+ }
+ Intent intent = new Intent(context, HomeActivity.class);
+ intent.putExtra(Constant.NOTIFYCATION_INTENT_FROM, "recommandTask");
+ intent.putExtra(Constant.NOTIFYCATION_TASK_GEOM, wkt);
+ intent.putExtra(Constant.NOTIFYCATION_TASK_ZOOM, zoom);
+ PendingIntent pendingIntent = PendingIntent.getActivity(context, id, intent, 0);
+ NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context, mBigImageChannelId)
+ .setContentTitle(contentTitle)
+ .setContentText(contentText)
+ .setStyle(new NotificationCompat.BigPictureStyle().bigPicture(bigPic))
+ .setSmallIcon(R.mipmap.ic_launcher)
+ .setSilent(false)
+ .setLargeIcon(bigPic)
+ .setAutoCancel(true)
+ .setContentIntent(pendingIntent)
+ .addAction(R.mipmap.ic_launcher, "去看看", pendingIntent);
+ mManager.notify(1, mBuilder.build());
+ // 用户点击该提醒后跳转到主界面,并自动定位到指定位置
}
/**
@@ -102,6 +223,7 @@ public class MessageReceiver extends XGPushBaseReceiver {
// 在这里拿token
String token = message.getToken();
text = "注册成功1. token:" + token;
+ Constant.PUSH_TOKEN =token;
} else {
text = message + "注册失败,错误码:" + errorCode;
}
@@ -270,7 +392,7 @@ public class MessageReceiver extends XGPushBaseReceiver {
}
private void show(Context context, String text) {
- Toast.makeText(context, text, Toast.LENGTH_SHORT).show();
+// Toast.makeText(context, text, Toast.LENGTH_SHORT).show();
}
}
diff --git a/app/src/main/java/com/navinfo/outdoor/service/ForegroundCoreService.kt b/app/src/main/java/com/navinfo/outdoor/service/ForegroundCoreService.kt
new file mode 100644
index 0000000..d7d15c8
--- /dev/null
+++ b/app/src/main/java/com/navinfo/outdoor/service/ForegroundCoreService.kt
@@ -0,0 +1,26 @@
+package com.navinfo.outdoor.service
+
+import android.app.Service
+import android.content.Intent
+import android.os.IBinder
+
+class ForegroundCoreService : Service() {
+ override fun onBind(intent: Intent?): IBinder? = null
+ private val mForegroundNF:ForegroundNF by lazy {ForegroundNF(this)}
+ override fun onCreate() {
+ super.onCreate()
+ mForegroundNF.startForegroundNotification()
+ }
+ override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
+ if(null == intent){
+ //服务被系统kill掉之后重启进来的
+ return START_NOT_STICKY
+ }
+ mForegroundNF.startForegroundNotification()
+ return super.onStartCommand(intent, flags, startId)
+ }
+ override fun onDestroy() {
+ mForegroundNF.stopForegroundNotification()
+ super.onDestroy()
+ }
+}
diff --git a/app/src/main/java/com/navinfo/outdoor/service/ForegroundNF.kt b/app/src/main/java/com/navinfo/outdoor/service/ForegroundNF.kt
new file mode 100644
index 0000000..c2389ee
--- /dev/null
+++ b/app/src/main/java/com/navinfo/outdoor/service/ForegroundNF.kt
@@ -0,0 +1,83 @@
+package com.navinfo.outdoor.service
+
+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.core.app.NotificationCompat
+import com.navinfo.outdoor.R
+import com.navinfo.outdoor.activity.HomeActivity
+
+//初始化前台通知,停止前台通知
+class ForegroundNF(private val service: ForegroundCoreService) : ContextWrapper(service) {
+ companion object {
+ private const val START_ID = 101
+ private const val CHANNEL_ID = "app_foreground_service"
+ private const val CHANNEL_NAME = "前台保活服务"
+ }
+ private var mNotificationManager: NotificationManager? = null
+
+ private var mCompatBuilder: NotificationCompat.Builder?=null
+
+ private val compatBuilder: NotificationCompat.Builder?
+ get() {
+ if (mCompatBuilder == null) {
+ val notificationIntent = Intent(this, HomeActivity::class.java)
+ notificationIntent.action = Intent.ACTION_MAIN
+ notificationIntent.addCategory(Intent.CATEGORY_LAUNCHER)
+ notificationIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
+ //动作意图
+ val pendingIntent = PendingIntent.getActivity(
+ this, (Math.random() * 10 + 10).toInt(),
+ notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT
+ )
+ val notificationBuilder: NotificationCompat.Builder = NotificationCompat.Builder(this,CHANNEL_ID)
+ //标题
+ notificationBuilder.setContentTitle("地图寻宝3")
+ //通知内容
+ notificationBuilder.setContentText("地图寻宝3正在运行中")
+ //状态栏显示的小图标
+ notificationBuilder.setSmallIcon(R.mipmap.ic_launcher)
+ //通知内容打开的意图
+ notificationBuilder.setContentIntent(pendingIntent)
+ mCompatBuilder = notificationBuilder
+ }
+ return mCompatBuilder
+ }
+
+ init {
+ createNotificationChannel()
+ }
+
+ //创建通知渠道
+ private fun createNotificationChannel() {
+ mNotificationManager =
+ getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
+ //针对8.0+系统
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ val channel = NotificationChannel(
+ CHANNEL_ID,
+ CHANNEL_NAME,
+ NotificationManager.IMPORTANCE_LOW
+ )
+ channel.lockscreenVisibility = Notification.VISIBILITY_PUBLIC
+ channel.setShowBadge(false)
+ mNotificationManager?.createNotificationChannel(channel)
+ }
+ }
+
+ //开启前台通知
+ fun startForegroundNotification() {
+ service.startForeground(START_ID, compatBuilder?.build())
+ }
+
+ //停止前台服务并清除通知
+ fun stopForegroundNotification() {
+ mNotificationManager?.cancelAll()
+ service.stopForeground(true)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/navinfo/outdoor/util/WhiteListHelper.java b/app/src/main/java/com/navinfo/outdoor/util/WhiteListHelper.java
new file mode 100644
index 0000000..ee40c2a
--- /dev/null
+++ b/app/src/main/java/com/navinfo/outdoor/util/WhiteListHelper.java
@@ -0,0 +1,144 @@
+package com.navinfo.outdoor.util;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Build;
+import android.os.PowerManager;
+import android.provider.Settings;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+import androidx.lifecycle.DefaultLifecycleObserver;
+import androidx.lifecycle.LifecycleOwner;
+
+/**
+ * Android实现添加到系统白名单的工具类
+ * */
+public class WhiteListHelper {
+ final static String IS_HUAWEI = "isHuawei"; //华为
+ final static String IS_XIAOMI = "isXiaomi"; //小米
+ final static String IS_OPPO = "isOppo"; //oppo
+ final static String IS_VIVO = "isVivo"; //vivo
+ final static String IS_MEIZU = "isMeizu"; //魅族
+ final static String IS_SAMSUNG = "isSamsung"; //三星
+ final static String IS_LETV = "isLetv"; //乐视
+ final static String IS_SMARTISAN = "isSmartisan"; //锤子
+
+ /**
+ * 判断当前应用是否在系统白名单内
+ * */
+ @RequiresApi(Build.VERSION_CODES.M)
+ public boolean isIgnoringBatteryOptimizations(Context context){
+ boolean isIgnoring = false;
+ PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+
+ if (powerManager != null)
+ isIgnoring = powerManager.isIgnoringBatteryOptimizations("包名");
+
+ return isIgnoring;
+ }
+
+ /**
+ * 请求系统白名单
+ * */
+ public void requestIgnoreBatteryOptimizations(Context context){
+ try {
+ Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
+ intent.setData(Uri.parse("package:" + "com.navinfo.outdoor"));
+ context.startActivity(intent);
+ }catch (Exception e){
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * 跳转到指定应用的首页
+ */
+ public void showActivity(String packageName,Context context){
+ Intent intent = context.getPackageManager().getLaunchIntentForPackage(packageName);
+ context.startActivity(intent);
+ }
+ /**
+ * 跳转到指定应用的指定页面
+ * */
+ public void showActivity(String packageName,String activityDir,Context context){
+ Intent intent = new Intent();
+ intent.setComponent(new ComponentName(packageName, activityDir));
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ context.startActivity(intent);
+ }
+
+ //判断手机厂商
+ public String checkPhoneFirm(){
+ String phoneState = Build.BRAND.toLowerCase(); //获取手机厂商
+ if (phoneState.equals("huawei") || phoneState.equals("honor"))
+ return WhiteListHelper.IS_HUAWEI;
+ else if (phoneState.equals("xiaomi") && Build.BRAND != null)
+ return WhiteListHelper.IS_XIAOMI;
+ else if (phoneState.equals("oppo") && Build.BRAND != null)
+ return WhiteListHelper.IS_OPPO;
+ else if (phoneState.equals("vivo") && Build.BRAND != null)
+ return WhiteListHelper.IS_VIVO;
+ else if (phoneState.equals("meizu") && Build.BRAND != null)
+ return WhiteListHelper.IS_MEIZU;
+ else if (phoneState.equals("samsung") && Build.BRAND != null)
+ return WhiteListHelper.IS_SAMSUNG;
+ else if (phoneState.equals("letv") && Build.BRAND != null)
+ return WhiteListHelper.IS_LETV;
+ else if (phoneState.equals("smartisan") && Build.BRAND != null)
+ return WhiteListHelper.IS_SMARTISAN;
+
+ return "";
+ }
+
+ //前往设置白名单管理界面
+ public void gotoWhiteListSetting(Context context){
+ if (checkPhoneFirm().equals(WhiteListHelper.IS_HUAWEI)){
+ try {
+ showActivity("com.huawei.systemmanager","com.huawei.systemmanager.startupmgr.ui.StartupNormalAppListActivity",context);
+ }catch (Exception e){
+ showActivity("com.huawei.systemmanager",
+ "com.huawei.systemmanager.optimize.bootstart.BootStartActivity",context);
+ }
+ }else if (checkPhoneFirm().equals(WhiteListHelper.IS_XIAOMI)){
+ showActivity("com.miui.securitycenter",
+ "com.miui.permcenter.autostart.AutoStartManagementActivity",context);
+ }else if (checkPhoneFirm().equals(WhiteListHelper.IS_OPPO)){
+ //oppo:操作步骤:权限隐私 -> 自启动管理 -> 允许应用自启动
+ try {
+ showActivity("com.coloros.phonemanager",context);
+ } catch (Exception e) {
+ try {
+ showActivity("com.oppo.safe",context);
+ } catch (Exception e2) {
+ try {
+ showActivity("com.coloros.oppoguardelf", context);
+ } catch (Exception e3) {
+ showActivity("com.coloros.safecenter", context);
+ }
+ }
+ }
+ }else if (checkPhoneFirm().equals(WhiteListHelper.IS_VIVO)){
+ //vivo:操作步骤:权限管理 -> 自启动 -> 允许应用自启动
+ showActivity("com.iqoo.secure", context);
+ }else if (checkPhoneFirm().equals(WhiteListHelper.IS_MEIZU)){
+ //魅族:操作步骤:权限管理 -> 后台管理 -> 点击应用 -> 允许后台运行
+ showActivity("com.meizu.safe", context);
+ }else if (checkPhoneFirm().equals(WhiteListHelper.IS_SAMSUNG)){
+ //三星:操作步骤:自动运行应用程序 -> 打开应用开关 -> 电池管理 -> 未监视的应用程序 -> 添加应用
+ try {
+ showActivity("com.samsung.android.sm_cn",context);
+ } catch (Exception e) {
+ showActivity("com.samsung.android.sm",context);
+ }
+ }else if (checkPhoneFirm().equals(WhiteListHelper.IS_LETV)){
+ //乐视:操作步骤:自启动管理 -> 允许应用自启动
+ showActivity("com.letv.android.letvsafe","com.letv.android.letvsafe.AutobootManageActivity", context);
+ }else if (checkPhoneFirm().equals(WhiteListHelper.IS_SMARTISAN)){
+ //锤子:操作步骤:权限管理 -> 自启动权限管理 -> 点击应用 -> 允许被系统启动
+ showActivity("com.smartisanos.security", context );
+ }
+ }
+}