|
|
package com.xypower.mpmaster;
|
|
|
|
|
|
import android.app.AlarmManager;
|
|
|
import android.app.Notification;
|
|
|
import android.app.NotificationChannel;
|
|
|
import android.app.NotificationManager;
|
|
|
import android.app.PendingIntent;
|
|
|
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.pm.PackageInfo;
|
|
|
import android.content.pm.PackageManager;
|
|
|
import android.net.ConnectivityManager;
|
|
|
import android.os.BatteryManager;
|
|
|
import android.os.Build;
|
|
|
import android.os.Environment;
|
|
|
import android.os.Handler;
|
|
|
import android.os.IBinder;
|
|
|
import android.os.Message;
|
|
|
import android.os.Messenger;
|
|
|
import android.os.PowerManager;
|
|
|
import android.os.SystemClock;
|
|
|
import android.telephony.SignalStrength;
|
|
|
import android.telephony.TelephonyManager;
|
|
|
import android.text.TextUtils;
|
|
|
import android.text.format.DateFormat;
|
|
|
import android.util.Log;
|
|
|
import android.widget.RemoteViews;
|
|
|
import android.widget.Toast;
|
|
|
|
|
|
import androidx.core.app.NotificationCompat;
|
|
|
|
|
|
import com.dev.devapi.api.SysApi;
|
|
|
import com.xypower.common.FileDownloader;
|
|
|
import com.xypower.common.InetAddressUtils;
|
|
|
import com.xypower.common.JSONUtils;
|
|
|
import com.xypower.common.MicroPhotoContext;
|
|
|
|
|
|
import org.json.JSONObject;
|
|
|
|
|
|
import java.io.File;
|
|
|
import java.net.InetAddress;
|
|
|
import java.util.Date;
|
|
|
import java.util.HashMap;
|
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
|
import java.util.logging.FileHandler;
|
|
|
import java.util.logging.Level;
|
|
|
import java.util.logging.Logger;
|
|
|
|
|
|
public class MpMasterService extends Service {
|
|
|
static {
|
|
|
System.loadLibrary("mpmaster");
|
|
|
}
|
|
|
|
|
|
public static final String TAG = "MPMST";
|
|
|
|
|
|
public Logger logger;
|
|
|
|
|
|
public final static int MSG_WHAT_SENDING_HB = 40;
|
|
|
public static final int NOTIFICATION_ID_FOREGROUND_SERVICE = 8466503;
|
|
|
public static final String ACTION_MSG_BROADCAST = "ACT_MSG_BROADCAST";
|
|
|
|
|
|
public static final String ACTION_START = "com.xypower.mpmaster.ACT_START";
|
|
|
public static final String ACTION_STOP = "com.xypower.mpmaster.ACT_STOP";
|
|
|
public static final String ACTION_MAIN = "com.xypower.mpmaster.ACT_MAIN";
|
|
|
|
|
|
public static final String ACTION_UPD_OTA = "com.xy.otaupdateresult";
|
|
|
|
|
|
private static final String ACTION_UPDATE_CONFIGS = "com.xypower.mpmaster.ACT_UPD_CFG";
|
|
|
|
|
|
private static final String ACTION_HEARTBEAT = "com.xypower.mpmaster.ACT_HB";
|
|
|
private static final String ACTION_TAKE_PHOTO = "com.xypower.mpapp.ACT_TP";
|
|
|
|
|
|
public static final String ACTION_IMP_PUBKRY = "com.xypower.mpapp.ACT_IMP_PUBKEY";
|
|
|
|
|
|
private static final String EXTRA_PARAM_SCHEDULES = "Schedules";
|
|
|
private static final String EXTRA_PARAM_SCHEDULE = "Schedule_";
|
|
|
private static final String EXTRA_PARAM_TIME = "Time";
|
|
|
private static final String FOREGROUND_CHANNEL_ID = "foreground_channel_id";
|
|
|
public static class STATE_SERVICE {
|
|
|
public static final int CONNECTED = 10;
|
|
|
public static final int NOT_CONNECTED = 0;
|
|
|
}
|
|
|
private static int mStateService = STATE_SERVICE.NOT_CONNECTED;
|
|
|
|
|
|
private boolean mMntnMode = false;
|
|
|
private boolean mQuickHbMode = false;
|
|
|
private boolean mUsingAbsHbTime = false;
|
|
|
private String mCmdid = "";
|
|
|
private NotificationManager mNotificationManager;
|
|
|
private int mQuickHeartbeatDuration = 60; // 1m = 60 s
|
|
|
private int mHeartbeatDuration = 600; // 10m = 10 * 60s
|
|
|
|
|
|
private AlarmReceiver mAlarmReceiver = null;
|
|
|
private ScreenActionReceiver mScreenaAtionReceiver = null;
|
|
|
private UpdateReceiver mUpdateReceiver = null;
|
|
|
|
|
|
private ServiceHandler mHander = null;
|
|
|
|
|
|
private String mModelName = null;
|
|
|
|
|
|
private static String mMpAppVersion = null;
|
|
|
private static String mMpMasterVersion = null;
|
|
|
|
|
|
private String mSerialNo = null;
|
|
|
|
|
|
private long mTimeToStartMpApp = 0;
|
|
|
private long mTimeOfMpAppAlive = 1800000; // 30minutes
|
|
|
private int mAbsHeartbeatTimes[] = null;
|
|
|
|
|
|
private boolean mSeparateNetwork = false;
|
|
|
|
|
|
public MpMasterService() {
|
|
|
}
|
|
|
@Override
|
|
|
public IBinder onBind(Intent intent) {
|
|
|
// TODO: Return the communication channel to the service.
|
|
|
throw new UnsupportedOperationException("Not yet implemented");
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public void onCreate() {
|
|
|
super.onCreate();
|
|
|
|
|
|
loadConfig();
|
|
|
|
|
|
logger = Logger.getLogger("com.xypower.mpmaster.logger");
|
|
|
logger.setLevel(Level.ALL);
|
|
|
// LogFormatter.installFormatter(logger);
|
|
|
LogFormatter logFormatter = new LogFormatter();
|
|
|
|
|
|
if (BuildConfig.DEBUG) {
|
|
|
LogcatHandler logcatHandler = new LogcatHandler(TAG);
|
|
|
logcatHandler.setFormatter(logFormatter);
|
|
|
logger.addHandler(logcatHandler);
|
|
|
}
|
|
|
|
|
|
FileHandler fileHandler = null;
|
|
|
try {
|
|
|
String appPath = MicroPhotoContext.buildMasterAppDir(getApplicationContext());
|
|
|
String logPath = appPath + "logs";
|
|
|
File fi = new File(logPath);
|
|
|
if (!fi.exists()) {
|
|
|
fi.mkdirs();
|
|
|
}
|
|
|
|
|
|
File logFile = new File(fi, "log.txt");
|
|
|
|
|
|
fileHandler = new FileHandler(logFile.getAbsolutePath(), true);//true表示日志内容在文件中追加
|
|
|
fileHandler.setLevel(Level.ALL);//级别为ALL,记录所有消息
|
|
|
|
|
|
fileHandler.setFormatter(logFormatter);
|
|
|
logger.addHandler(fileHandler);
|
|
|
|
|
|
} catch (Throwable e) {
|
|
|
System.out.println("创建文件失败!" + e.getMessage());
|
|
|
}
|
|
|
|
|
|
try {
|
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
|
mSerialNo = Build.getSerial();
|
|
|
} else {
|
|
|
mSerialNo = Build.SERIAL;
|
|
|
}
|
|
|
} catch (Exception ex) {
|
|
|
ex.printStackTrace();
|
|
|
}
|
|
|
|
|
|
mMpMasterVersion = MicroPhotoContext.getVersionName(getApplicationContext());
|
|
|
PackageManager packageManager = getPackageManager();
|
|
|
PackageInfo packageInfo = null;
|
|
|
try {
|
|
|
packageInfo = packageManager.getPackageInfo(MicroPhotoContext.PACKAGE_NAME_MPAPP, 0);
|
|
|
} catch (Exception ex) {
|
|
|
ex.printStackTrace();
|
|
|
}
|
|
|
mMpAppVersion = packageInfo == null ? "" : packageInfo.versionName;
|
|
|
|
|
|
logger.info("MpMaster started version=" + mMpMasterVersion);
|
|
|
|
|
|
mHander = new ServiceHandler();
|
|
|
|
|
|
mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
|
|
mStateService = STATE_SERVICE.NOT_CONNECTED;
|
|
|
|
|
|
mScreenaAtionReceiver = new ScreenActionReceiver();
|
|
|
|
|
|
// 注册广播接受者
|
|
|
{
|
|
|
mAlarmReceiver = new AlarmReceiver(this);
|
|
|
IntentFilter intentFilter = new IntentFilter(ACTION_HEARTBEAT);
|
|
|
// intentFilter.addAction(ACTION_TAKE_PHOTO);
|
|
|
// intentFilter.addAction(ACTION_TIMEOUT);
|
|
|
// intentFilter.addAction(ACTION_TAKE_PHOTO_MANUALLY);
|
|
|
intentFilter.addAction(ACTION_MSG_BROADCAST);
|
|
|
intentFilter.addAction(ACTION_UPDATE_CONFIGS);
|
|
|
intentFilter.addAction(ACTION_UPD_OTA);
|
|
|
registerReceiver(mAlarmReceiver, intentFilter);
|
|
|
}
|
|
|
|
|
|
{
|
|
|
mUpdateReceiver = new UpdateReceiver();
|
|
|
IntentFilter intentFilter = new IntentFilter();
|
|
|
intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
|
|
|
intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
|
|
|
intentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED);
|
|
|
intentFilter.addDataScheme("package");
|
|
|
registerReceiver(mUpdateReceiver, intentFilter);
|
|
|
}
|
|
|
|
|
|
// AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
|
|
|
|
|
|
startMaster();
|
|
|
startMpApp();
|
|
|
|
|
|
registerHeartbeatTimer();
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public void onDestroy() {
|
|
|
|
|
|
mStateService = STATE_SERVICE.NOT_CONNECTED;
|
|
|
|
|
|
logger.warning("MicroPhotoService::onDestroy called");
|
|
|
|
|
|
unregisterReceiver(mAlarmReceiver);
|
|
|
unregisterReceiver(mScreenaAtionReceiver);
|
|
|
unregisterReceiver(mUpdateReceiver);
|
|
|
|
|
|
super.onDestroy();
|
|
|
}
|
|
|
|
|
|
public static class ServiceHandler extends Handler {
|
|
|
@Override
|
|
|
public void dispatchMessage(Message msg) {
|
|
|
super.dispatchMessage(msg);
|
|
|
// Log.i("life", "MyHandler----dispatchMessage");
|
|
|
// Log.i("life", Thread.currentThread().getName());
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public void handleMessage(Message msg) {
|
|
|
super.handleMessage(msg);
|
|
|
// Log.i("life", "MyHandler----handleMessage");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
protected void loadConfig() {
|
|
|
MicroPhotoContext.MasterConfig masterConfig = MicroPhotoContext.getMasterConfig(getApplicationContext());
|
|
|
mMntnMode = masterConfig.mntnMode != 0;
|
|
|
mQuickHbMode = masterConfig.quickHbMode != 0;
|
|
|
mUsingAbsHbTime = masterConfig.usingAbsHbTime != 0;
|
|
|
mHeartbeatDuration = masterConfig.heartbeat * 60; // minute to second
|
|
|
mAbsHeartbeatTimes = masterConfig.absHeartbeats;
|
|
|
mSeparateNetwork = masterConfig.separateNetwork != 0;
|
|
|
mTimeOfMpAppAlive = masterConfig.mpappMonitorTimeout;
|
|
|
}
|
|
|
|
|
|
// public boolean useSeparater
|
|
|
public String getCmdid() {
|
|
|
return mCmdid;
|
|
|
}
|
|
|
|
|
|
public boolean isSeparateNetwork() {
|
|
|
return mSeparateNetwork;
|
|
|
}
|
|
|
|
|
|
public boolean isMntnMode() {
|
|
|
return mMntnMode;
|
|
|
}
|
|
|
|
|
|
public void startMpApp() {
|
|
|
try {
|
|
|
final Context context = getApplicationContext();
|
|
|
|
|
|
if (MicroPhotoContext.isAppAlive(context, MicroPhotoContext.PACKAGE_NAME_MPAPP)) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
String appPath = MicroPhotoContext.buildMpAppDir(context);
|
|
|
long ts = System.currentTimeMillis();
|
|
|
if (ts - mTimeToStartMpApp < 30000) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
File mpappDb = new File(appPath + "data/App.db");
|
|
|
long modifiedTimeOfDb = 0;
|
|
|
if (mpappDb.exists()) {
|
|
|
modifiedTimeOfDb = mpappDb.lastModified();
|
|
|
}
|
|
|
if ((ts - modifiedTimeOfDb) > mTimeOfMpAppAlive) {
|
|
|
// greater than 30m
|
|
|
logger.warning("Start MpAPP as it is NOT running");
|
|
|
MicroPhotoContext.restartMpApp(context);
|
|
|
mTimeToStartMpApp = ts;
|
|
|
}
|
|
|
} catch (Exception ex) {
|
|
|
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public String getMpAppVersion() {
|
|
|
if (TextUtils.isEmpty(mMpAppVersion)) {
|
|
|
PackageManager packageManager = getPackageManager();
|
|
|
PackageInfo packageInfo = null;
|
|
|
try {
|
|
|
packageInfo = packageManager.getPackageInfo(MicroPhotoContext.PACKAGE_NAME_MPAPP, 0);
|
|
|
} catch (Exception ex) {
|
|
|
ex.printStackTrace();
|
|
|
}
|
|
|
mMpAppVersion = packageInfo == null ? "" : packageInfo.versionName;
|
|
|
}
|
|
|
return mMpAppVersion;
|
|
|
}
|
|
|
|
|
|
public static void resetVersions() {
|
|
|
mMpAppVersion = null;
|
|
|
mMpMasterVersion = null;
|
|
|
}
|
|
|
|
|
|
public String getMasterAppVersion() {
|
|
|
if (TextUtils.isEmpty(mMpMasterVersion)) {
|
|
|
mMpMasterVersion = MicroPhotoContext.getVersionName(getApplicationContext());
|
|
|
}
|
|
|
return mMpMasterVersion;
|
|
|
}
|
|
|
|
|
|
public String getSerialNo() {
|
|
|
return mSerialNo;
|
|
|
}
|
|
|
|
|
|
static String convertSwitch(boolean swtch) {
|
|
|
return swtch ? "ON" : "OFF";
|
|
|
}
|
|
|
|
|
|
public void setMntnMode(boolean mntnMode, boolean quickHbMode) {
|
|
|
boolean oldMntnMode = mMntnMode;
|
|
|
boolean oldQuickHbMode = mQuickHbMode;
|
|
|
|
|
|
mMntnMode = mntnMode;
|
|
|
mQuickHbMode = quickHbMode;
|
|
|
|
|
|
if (oldMntnMode != mntnMode || oldQuickHbMode != quickHbMode) {
|
|
|
MicroPhotoContext.MasterConfig masterConfig = MicroPhotoContext.getMasterConfig(getApplicationContext());
|
|
|
|
|
|
masterConfig.mntnMode = mntnMode ? 1 : 0;
|
|
|
masterConfig.quickHbMode = quickHbMode ? 1 : 0;
|
|
|
|
|
|
MicroPhotoContext.saveMasterConfig(getApplicationContext(), masterConfig);
|
|
|
|
|
|
logger.warning("MNTN Mode Changed from " + convertSwitch(oldMntnMode) + " to " + convertSwitch(mntnMode)
|
|
|
+ " Quick Heartbeat from" + convertSwitch(oldQuickHbMode) + " to " + convertSwitch(quickHbMode));
|
|
|
}
|
|
|
|
|
|
if (oldQuickHbMode != quickHbMode) {
|
|
|
// Cancel cuurent job first
|
|
|
|
|
|
if (quickHbMode) {
|
|
|
registerHeartbeatTimer();
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private void startMaster() {
|
|
|
String masterUrl = MicroPhotoContext.DEFAULT_MASTER_URL;
|
|
|
|
|
|
MicroPhotoContext.MasterConfig masterConfig = MicroPhotoContext.getMasterConfig(getApplicationContext());
|
|
|
String url = masterConfig.getUrl();
|
|
|
if (!TextUtils.isEmpty(url)) {
|
|
|
masterUrl = url;
|
|
|
}
|
|
|
|
|
|
MicroPhotoContext.AppConfig appConfig = MicroPhotoContext.getMpAppConfig(getApplicationContext());
|
|
|
|
|
|
logger.warning("Start Mntn report:" + masterUrl);
|
|
|
|
|
|
AppMaster appMaster = new AppMaster(this, masterUrl, appConfig.cmdid);
|
|
|
appMaster.start();
|
|
|
}
|
|
|
|
|
|
public static class AlarmReceiver extends BroadcastReceiver {
|
|
|
private MpMasterService mService;
|
|
|
public AlarmReceiver() {
|
|
|
mService = null;
|
|
|
}
|
|
|
public AlarmReceiver(MpMasterService service) {
|
|
|
mService = service;
|
|
|
}
|
|
|
public void onReceive(Context context, Intent intent) {
|
|
|
String action = intent.getAction();
|
|
|
if (TextUtils.equals(ACTION_HEARTBEAT, action)) {
|
|
|
mService.logger.info("Heartbeat Timer Fired ACTION=" + action);
|
|
|
|
|
|
mService.registerHeartbeatTimer();
|
|
|
|
|
|
mService.startMaster();
|
|
|
mService.startMpApp();
|
|
|
|
|
|
} else if (TextUtils.equals(ACTION_UPDATE_CONFIGS, action)) {
|
|
|
int restart = intent.getIntExtra("restart", 0);
|
|
|
mService.logger.info("Update Config Fired ACTION=" + action + " restart=" + restart);
|
|
|
if (restart != 0) {
|
|
|
mService.restartApp(context, context.getPackageName());
|
|
|
} else {
|
|
|
mService.loadConfig();
|
|
|
}
|
|
|
} else if (TextUtils.equals(ACTION_UPD_OTA, action)) {
|
|
|
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
private void registerHeartbeatTimer(int duration) {
|
|
|
int orgHeartbeatDuration = mHeartbeatDuration;
|
|
|
mHeartbeatDuration = duration;
|
|
|
if (orgHeartbeatDuration == 0) {
|
|
|
registerHeartbeatTimer();
|
|
|
}
|
|
|
|
|
|
}
|
|
|
private void registerHeartbeatTimer() {
|
|
|
|
|
|
Intent alarmIntent = new Intent();
|
|
|
alarmIntent.setAction(ACTION_HEARTBEAT);
|
|
|
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, 0);
|
|
|
|
|
|
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
|
|
|
long timeout = mHeartbeatDuration;
|
|
|
if (mMntnMode && mQuickHbMode) {
|
|
|
timeout = mQuickHeartbeatDuration;
|
|
|
} else {
|
|
|
|
|
|
}
|
|
|
|
|
|
alarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + timeout * 1000, pendingIntent);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public int onStartCommand(Intent intent, int flags, int startId) {
|
|
|
|
|
|
if (intent == null) {
|
|
|
stopForeground(true);
|
|
|
stopSelf();
|
|
|
return START_NOT_STICKY;
|
|
|
}
|
|
|
|
|
|
// if user starts the service
|
|
|
switch (intent.getAction()) {
|
|
|
case ACTION_START:
|
|
|
Log.d(TAG, "Received user starts foreground intent");
|
|
|
startForeground(NOTIFICATION_ID_FOREGROUND_SERVICE, prepareNotification());
|
|
|
|
|
|
connect();
|
|
|
|
|
|
registerReceiver(mScreenaAtionReceiver, mScreenaAtionReceiver.getFilter());
|
|
|
|
|
|
String appPath = MicroPhotoContext.buildAppDir(this.getApplicationContext());
|
|
|
|
|
|
String cmdid = intent.getStringExtra("cmdid");
|
|
|
mCmdid = cmdid;
|
|
|
|
|
|
Log.i(TAG, "AppPath=" + appPath + " cmdid=" + cmdid);
|
|
|
|
|
|
registerHeartbeatTimer();
|
|
|
|
|
|
startMaster();
|
|
|
|
|
|
break;
|
|
|
case ACTION_STOP:
|
|
|
unregisterReceiver(mScreenaAtionReceiver);
|
|
|
|
|
|
stopForeground(true);
|
|
|
stopSelf();
|
|
|
break;
|
|
|
default:
|
|
|
stopForeground(true);
|
|
|
stopSelf();
|
|
|
}
|
|
|
|
|
|
return START_NOT_STICKY;
|
|
|
}
|
|
|
|
|
|
private void connect() {
|
|
|
// after 10 seconds its connected
|
|
|
mHander.postDelayed(
|
|
|
new Runnable() {
|
|
|
public void run() {
|
|
|
Log.d(TAG, "Bluetooth Low Energy device is connected!!");
|
|
|
Toast.makeText(getApplicationContext(), "Connected!", Toast.LENGTH_SHORT).show();
|
|
|
mStateService = STATE_SERVICE.CONNECTED;
|
|
|
startForeground(NOTIFICATION_ID_FOREGROUND_SERVICE, prepareNotification());
|
|
|
}
|
|
|
}, 10000);
|
|
|
|
|
|
}
|
|
|
|
|
|
private Notification prepareNotification() {
|
|
|
// handle build version above android oreo
|
|
|
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O &&
|
|
|
mNotificationManager.getNotificationChannel(FOREGROUND_CHANNEL_ID) == null) {
|
|
|
CharSequence name = getString(R.string.text_name_notification);
|
|
|
int importance = NotificationManager.IMPORTANCE_DEFAULT;
|
|
|
NotificationChannel channel = new NotificationChannel(FOREGROUND_CHANNEL_ID, name, importance);
|
|
|
channel.enableVibration(false);
|
|
|
mNotificationManager.createNotificationChannel(channel);
|
|
|
}
|
|
|
|
|
|
Intent notificationIntent = new Intent(this, MainActivity.class);
|
|
|
notificationIntent.setAction(ACTION_MAIN);
|
|
|
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
|
|
|
|
|
// if min sdk goes below honeycomb
|
|
|
/*if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) {
|
|
|
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
|
|
} else {
|
|
|
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
|
}*/
|
|
|
|
|
|
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
|
|
|
|
|
// make a stop intent
|
|
|
Intent stopIntent = new Intent(this, MpMasterService.class);
|
|
|
stopIntent.setAction(ACTION_STOP);
|
|
|
PendingIntent pendingStopIntent = PendingIntent.getService(this, 0, stopIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
|
|
RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.notification);
|
|
|
remoteViews.setOnClickPendingIntent(R.id.btn_stop, pendingStopIntent);
|
|
|
|
|
|
// if it is connected
|
|
|
switch (mStateService) {
|
|
|
case STATE_SERVICE.NOT_CONNECTED:
|
|
|
remoteViews.setTextViewText(R.id.tv_state, "DISCONNECTED");
|
|
|
break;
|
|
|
case STATE_SERVICE.CONNECTED:
|
|
|
remoteViews.setTextViewText(R.id.tv_state, "CONNECTED");
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
// notification builder
|
|
|
NotificationCompat.Builder notificationBuilder;
|
|
|
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
|
|
|
notificationBuilder = new NotificationCompat.Builder(this, FOREGROUND_CHANNEL_ID);
|
|
|
} else {
|
|
|
notificationBuilder = new NotificationCompat.Builder(this);
|
|
|
}
|
|
|
notificationBuilder
|
|
|
.setContent(remoteViews)
|
|
|
.setSmallIcon(R.mipmap.ic_launcher)
|
|
|
.setCategory(NotificationCompat.CATEGORY_SERVICE)
|
|
|
.setOnlyAlertOnce(true)
|
|
|
.setOngoing(true)
|
|
|
.setAutoCancel(true)
|
|
|
.setContentIntent(pendingIntent);
|
|
|
|
|
|
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
|
|
|
notificationBuilder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
|
|
|
}
|
|
|
|
|
|
return notificationBuilder.build();
|
|
|
}
|
|
|
|
|
|
public String buildAppDir() {
|
|
|
|
|
|
String path = Environment.getExternalStorageDirectory().getAbsolutePath();
|
|
|
if (!path.endsWith(File.separator)) {
|
|
|
path += File.separator;
|
|
|
}
|
|
|
path += getApplicationContext().getPackageName() + File.separator;
|
|
|
File pathFile = new File(path);
|
|
|
if (!pathFile.exists() && !pathFile.mkdirs()) {
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
return path;
|
|
|
}
|
|
|
|
|
|
public boolean updateMntn(String url) {
|
|
|
if (TextUtils.isEmpty(url)) {
|
|
|
return false;
|
|
|
}
|
|
|
String path = buildAppDir();
|
|
|
path += "data/Master.json";
|
|
|
JSONObject jsonObject = JSONUtils.loadJson(path);
|
|
|
|
|
|
String oldUrl = null;
|
|
|
try {
|
|
|
oldUrl = jsonObject.getString("url");
|
|
|
} catch (Exception ex) {
|
|
|
ex.printStackTrace();
|
|
|
}
|
|
|
if (TextUtils.equals(url, oldUrl)) {
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
try {
|
|
|
jsonObject.put("url", url);
|
|
|
} catch (Exception ex) {
|
|
|
ex.printStackTrace();
|
|
|
}
|
|
|
|
|
|
return JSONUtils.saveJson(path, jsonObject);
|
|
|
}
|
|
|
|
|
|
public boolean updateTime(long timeInMillis) {
|
|
|
try {
|
|
|
SysApi.setSystemTime(getApplicationContext(), timeInMillis);
|
|
|
} catch (Exception ex) {
|
|
|
}
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
public void downloadAndInstall(final String url) {
|
|
|
|
|
|
final Context context = getApplicationContext();
|
|
|
final String tempPath = MicroPhotoContext.buildAppDir(context) + File.separator + "tmp";
|
|
|
File file = new File(tempPath);
|
|
|
file.mkdirs();
|
|
|
final String filePath = tempPath + File.separator + "mp.apk";
|
|
|
Thread th =new Thread(new Runnable() {
|
|
|
@Override
|
|
|
public void run() {
|
|
|
|
|
|
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
|
|
|
PowerManager.WakeLock wl = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, "com.xinyingpower.microphoto:Upgrader");
|
|
|
|
|
|
FileDownloader fd = new FileDownloader();
|
|
|
fd.download(url, filePath);
|
|
|
|
|
|
SysApi.installApk(context, filePath, context.getPackageName(), true);
|
|
|
|
|
|
try {
|
|
|
wl.setReferenceCounted(false);
|
|
|
wl.release();
|
|
|
} catch (Exception ex) {
|
|
|
ex.printStackTrace();
|
|
|
}
|
|
|
}
|
|
|
});
|
|
|
th.start();
|
|
|
}
|
|
|
|
|
|
public String getSystemInfo() {
|
|
|
|
|
|
boolean isXyPlatform = mModelName.startsWith("tb8788");
|
|
|
|
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
|
|
IntentFilter intentFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
|
|
|
Intent intent = getApplicationContext().registerReceiver(null, intentFilter);
|
|
|
|
|
|
int batteryStatus = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
|
|
|
int isCahrging = ((batteryStatus == BatteryManager.BATTERY_STATUS_CHARGING) ||
|
|
|
(batteryStatus == BatteryManager.BATTERY_STATUS_FULL)) ? 1 : 0;
|
|
|
|
|
|
int level = intent.getIntExtra("level", 0); ///电池剩余电量
|
|
|
int scale = intent.getIntExtra("scale", 0); ///获取电池满电量数值
|
|
|
// intent.getStringExtra("technology"); ///获取电池技术支持
|
|
|
// intent.getIntExtra("status",BatteryManager.BATTERY_STATUS_UNKNOWN); ///获取电池状态
|
|
|
// intent.getIntExtra("plugged", 0); ///获取电源信息
|
|
|
// intent.getIntExtra("health",BatteryManager.BATTERY_HEALTH_UNKNOWN); ///获取电池健康度
|
|
|
int bv = intent.getIntExtra("voltage", 0); /// mv
|
|
|
int temp = intent.getIntExtra("temperature", 0); ///获取电池温度
|
|
|
|
|
|
BatteryManager manager = (BatteryManager) getSystemService(BATTERY_SERVICE);
|
|
|
// manager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER);
|
|
|
int bca = manager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CURRENT_AVERAGE);
|
|
|
int bc = manager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CURRENT_NOW);
|
|
|
level = manager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY);
|
|
|
|
|
|
float bcaVal = (bca < 0) ? ((-bca)/1000000000) : (bca / 1000000000);
|
|
|
|
|
|
sb.append("&BC=" + Float.toString(bcaVal));
|
|
|
sb.append("&BV=" + Float.toString(((float)bv) / 1000));
|
|
|
sb.append("&BP=" + level);
|
|
|
sb.append("&BS=" + scale);
|
|
|
sb.append("&CS=" + isCahrging);
|
|
|
|
|
|
ConnectivityManager cm = (ConnectivityManager)getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
|
|
|
boolean isMetered = cm.isActiveNetworkMetered();
|
|
|
|
|
|
sb.append("&NS=" + (isMetered ? "1" : "0"));
|
|
|
|
|
|
final TelephonyManager telephonyManager = (TelephonyManager) getApplicationContext().getSystemService(Context.TELEPHONY_SERVICE);
|
|
|
|
|
|
SignalStrength ss = telephonyManager.getSignalStrength();
|
|
|
// List<CellSignalStrength> css = ss.getCellSignalStrengths();
|
|
|
|
|
|
if (ss != null) {
|
|
|
int signalLevel = ss.getLevel();
|
|
|
sb.append("&Signal4G=" + signalLevel);
|
|
|
sb.append("&Signal2G=" + signalLevel);
|
|
|
sb.append("&SL=" + signalLevel);
|
|
|
}
|
|
|
|
|
|
if (isXyPlatform) {
|
|
|
java.text.DecimalFormat fmt=new java.text.DecimalFormat("0.0");
|
|
|
|
|
|
double val = SysApi.getChargingVoltage() / 200.0;
|
|
|
sb.append("&CV=" + fmt.format(val)); // ChargeVol *5/1000
|
|
|
sb.append("&CC=" + SysApi.getChargingCurrent()); // ChargeCurrent
|
|
|
sb.append("&CP=" + SysApi.getChargingPower()); // ChargePower:
|
|
|
sb.append("&CBV=" + SysApi.getChargingBusVoltage()); // ChargeBusVol
|
|
|
val = SysApi.getBatteryVoltage() * 3.0 / 1000.0;
|
|
|
sb.append("&BV=" + fmt.format(val)); // BatVol
|
|
|
sb.append("&BC=" + SysApi.getBatteryCurrent()); // BatCurrent
|
|
|
sb.append("&BP=" + SysApi.getBatteryPower()); // BattaryPower
|
|
|
sb.append("&BBV=" + SysApi.getBatteryBusVoltage()); // BattaryBusVol
|
|
|
}
|
|
|
|
|
|
// SysApi.getCpuRate();
|
|
|
|
|
|
return sb.toString();
|
|
|
}
|
|
|
|
|
|
public void reboot(final int rebootType) {
|
|
|
|
|
|
Runnable runnable = new Runnable() {
|
|
|
@Override
|
|
|
public void run() {
|
|
|
if (rebootType == 0) {
|
|
|
Context context = MpMasterService.this.getApplicationContext();
|
|
|
restartApp(context, context.getPackageName());
|
|
|
|
|
|
} else {
|
|
|
Log.w(TAG, "Recv REBOOT command");
|
|
|
SysApi.reboot(MpMasterService.this.getApplicationContext());
|
|
|
}
|
|
|
}
|
|
|
};
|
|
|
mHander.postDelayed(runnable, 1000);
|
|
|
}
|
|
|
|
|
|
public static void restartApp(Context context, String packageName) {
|
|
|
/*
|
|
|
Context context = MicroPhotoService.this.getApplicationContext();
|
|
|
Intent intent = getPackageManager().getLaunchIntentForPackage(context.getPackageName());
|
|
|
|
|
|
int noDelay = 1;
|
|
|
intent.putExtra("noDelay", noDelay);
|
|
|
PendingIntent restartIntent = PendingIntent.getActivity(context, 0, intent, 0);
|
|
|
AlarmManager mgr = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
|
|
|
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 1000, restartIntent); // 1秒钟后重启应用
|
|
|
System.exit(0);
|
|
|
|
|
|
*/
|
|
|
|
|
|
Intent LaunchIntent = context.getPackageManager().getLaunchIntentForPackage(packageName);
|
|
|
LaunchIntent.putExtra("noDelay", 1);
|
|
|
LaunchIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
|
|
context.startActivity(LaunchIntent);
|
|
|
}
|
|
|
|
|
|
public void selectSimCard(int num) {
|
|
|
SysApi.selectSimCard4Data(getApplicationContext(), num);
|
|
|
}
|
|
|
|
|
|
public native static int getInt(int cmd);
|
|
|
public native static int[] getStats(long ts);
|
|
|
|
|
|
|
|
|
////////////////////////GPS////////////////////
|
|
|
|
|
|
} |