package com.xypower.mpapp; import static java.lang.System.loadLibrary; 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.Context; import android.content.Intent; import android.content.IntentFilter; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.location.LocationProvider; import android.net.ConnectivityManager; import android.net.Uri; import android.net.wifi.WifiManager; import android.os.BatteryManager; import android.os.Build; import android.os.Bundle; 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.RemoteException; import android.os.SystemClock; import androidx.core.app.NotificationCompat; import androidx.core.content.FileProvider; import android.telephony.SignalStrength; import android.telephony.SubscriptionManager; 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 com.dev.devapi.api.SysApi; import com.xypower.common.FileDownloader; import java.io.File; import java.lang.reflect.Method; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; public class MicroPhotoService extends Service { public static final String TAG = "MPLOG"; // Used to load the 'microphoto' library on application startup. static { loadLibrary("microphoto"); } public static final int MSG_WHAT_LOG = 10; public final static int MSG_WHAT_NETWORK_CHANGE = 20; public final static int MSG_WHAT_SERVICE_STATUS_CHANGE = 30; public final static int MSG_WHAT_MAX = 1000; private static final String ALARM_EVENT = "com.xinyingpower.mp.MicroPhotoService.AlarmReceiver"; public static final int NOTIFICATION_ID_FOREGROUND_SERVICE = 8466503; // public static final int NOTIFICATION_ID_FOREGROUND_SERVICE = 0; public static final String ACTION_START = "ACT_START"; public static final String ACTION_STOP = "ACT_STOP"; public static final String ACTION_MAIN = "ACT_MAIN"; private static final String ACTION_HEARTBEAT = "ACT_HB"; private static final String ACTION_TAKE_PHOTO = "ACT_TP"; private static final String ACTION_TAKE_PHOTO_MANUALLY = "ACT_TP_M"; private static final String ACTION_TIMEOUT = "ACT_TIMEOUT"; private static final String EXTRA_PARAM_CHANNEL = "Channel"; private static final String EXTRA_PARAM_PRESET = "Preset"; private static final String EXTRA_PARAM_PHOTO_OR_VIDEO = "PhotoOrVideo"; 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 String EXTRA_PARAM_FILENAME = "FileName"; private static final String EXTRA_PARAM_TIMER_UID = "TimerUid"; // private static String EXTRA_PARAM_TIMER_TYPE = "TimerType"; private static final String EXTRA_PARAM_TIMEOUT = "Timeout"; private static final String EXTRA_PARAM_TIMES = "Times"; private static final String EXTRA_PARAM_ELASPED_TIMES = "ElapsedTimes"; 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 String mCmdid = ""; private NotificationManager mNotificationManager; private final Map mWakeLocks = new HashMap<>(); private int mHeartbeatDuration = 0; // 5m: 5 * 60 * 1000 private long mNextHeartbeatTime = 0; private PositionManager mPositionManager = null; private final Map mTimers = new HashMap<>(); protected long mNativeHandle = 0; private AlarmReceiver mAlarmReceiver = null; private ScreenActionReceiver mScreenaAtionReceiver = null; private NetworkChangedReceiver mNetworkChangedReceiver = null; private ServiceHandler mHander = null; private Messenger mMessenger = null; private String mModelName = null; public MicroPhotoService() { } @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(); mHander = new ServiceHandler(); mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); mStateService = STATE_SERVICE.NOT_CONNECTED; DeviceUtil.getPhoneState(this.getApplicationContext()); 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); registerReceiver(mAlarmReceiver, intentFilter); } { mNetworkChangedReceiver = new NetworkChangedReceiver(this); IntentFilter filter = new IntentFilter(); filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); registerReceiver(mNetworkChangedReceiver, filter); } AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE); while (true) { AlarmManager.AlarmClockInfo aci = alarmManager.getNextAlarmClock(); if (aci == null) { break; } /* if (aci.getShowIntent().isBroadcast()) { // alarmManager.cancel(aci.getShowIntent()); } */ } // alarmManager.cancel(); // boolean res = false; // Environment.getExternalStoragePublicDirectory(String) // registerHeartbeatTimer(getHeartbeatDuration()); } @Override public void onDestroy() { mStateService = STATE_SERVICE.NOT_CONNECTED; Log.w(TAG, "MicroPhotoService::onDestroy called"); uninit(mNativeHandle); mNativeHandle = 0; unregisterReceiver(mAlarmReceiver); unregisterReceiver(mScreenaAtionReceiver); unregisterReceiver(mNetworkChangedReceiver); for(Map.Entry entry : mWakeLocks.entrySet()) { entry.getValue().release(); } mWakeLocks.clear(); 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"); } } public String getCmdid() { return mCmdid; } public static class AlarmReceiver extends BroadcastReceiver { private MicroPhotoService mService; public AlarmReceiver() { mService = null; } public AlarmReceiver(MicroPhotoService service) { mService = service; } public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (TextUtils.equals(ACTION_HEARTBEAT, action)) { Log.i(TAG, "HB Timer Fired ACTION=" + action); mService.sendHeartbeat(mService.mNativeHandle); mService.registerHeartbeatTimer(); String cmdid = mService.getCmdid(); if (!TextUtils.isEmpty(cmdid)) { AppMaster appMaster = new AppMaster(mService, cmdid); appMaster.start(); } } else if (TextUtils.equals(ACTION_TAKE_PHOTO, action)) { long ts = intent.getLongExtra(EXTRA_PARAM_TIME, 0); int cnt = intent.getIntExtra(EXTRA_PARAM_SCHEDULES, 0); if (cnt > 0) { for (int idx = 0; idx < cnt; idx++) { long val = intent.getLongExtra(EXTRA_PARAM_SCHEDULE + idx, 0); int channel = (int) ((val & 0xFF0000L) >> 16); int preset = (int) ((val & 0xFF00L) >> 8); Log.i(TAG, "PhotoTimer Fired: CH=" + channel + " PR=" + preset); mService.notifyToTakePhoto(mService.mNativeHandle, channel, preset, ts, mService.buildPhotoDir(mService.getApplicationContext(), channel), mService.buildPhotoFileName(channel, preset, ts), true); } } // Register Next Photo Timer Date date = new Date(); long nowTs = date.getTime() / 1000; date.setHours(0); date.setMinutes(0); date.setSeconds(0); long startTime = date.getTime() / 1000; long baseTime = nowTs - startTime; mService.registerCaptureSchedule(startTime, baseTime); } else if (TextUtils.equals(ACTION_TAKE_PHOTO_MANUALLY, action)) { int channel = intent.getIntExtra(EXTRA_PARAM_CHANNEL, 0); int preset = intent.getIntExtra(EXTRA_PARAM_PRESET, 0); // long ts = intent.getLongExtra(EXTRA_PARAM_TIME, 0); boolean photoOrVideo = intent.getBooleanExtra(EXTRA_PARAM_PHOTO_OR_VIDEO, true); long ts = System.currentTimeMillis() / 1000; Log.i(TAG, "Take Photo CH=" + channel + " PR=" + preset + " Mannually"); mService.notifyToTakePhoto(mService.mNativeHandle, channel, preset, ts, mService.buildPhotoDir(mService.getApplicationContext(), channel), mService.buildPhotoFileName(channel, preset, ts), photoOrVideo); } else if (TextUtils.equals(ACTION_TIMEOUT, action)) { long uid = intent.getLongExtra(EXTRA_PARAM_TIMER_UID, 0); long expectedTimes = intent.getLongExtra(EXTRA_PARAM_TIMES, 0); long elapsedTimes = intent.getLongExtra(EXTRA_PARAM_ELASPED_TIMES, 0); elapsedTimes++; Log.i(TAG, "Timeout uid=" + uid + " expectedTimes=" + expectedTimes + " Times=" + elapsedTimes); mService.fireTimeout(mService.mNativeHandle, uid, elapsedTimes); intent.putExtra(EXTRA_PARAM_ELASPED_TIMES, elapsedTimes); Long uidObj = Long.valueOf(uid); if ((expectedTimes == 0) || (elapsedTimes < expectedTimes)) { int timeout = intent.getIntExtra(EXTRA_PARAM_TIMEOUT, 0); PendingIntent pendingIntent = mService.mTimers.get(uidObj); if (pendingIntent != null) { mService.registerTimer(pendingIntent, uid, timeout); } } else { mService.mTimers.remove(uidObj); } } } } 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); alarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + mHeartbeatDuration, pendingIntent); mNextHeartbeatTime = System.currentTimeMillis() + mHeartbeatDuration; // alarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + timeout, pendingIntent); } private static void registerPhotoTimer(Context context, int channel, int preset, long ts, long timeout, List schedules) { // 创建延迟意图 Intent alarmIntent = new Intent(); alarmIntent.setAction(ACTION_TAKE_PHOTO); int cnt = schedules.size(); alarmIntent.putExtra(EXTRA_PARAM_SCHEDULES, cnt); String channelStr = ""; for (int idx = 0; idx < cnt; idx++) { long val = schedules.get(idx).longValue(); alarmIntent.putExtra(EXTRA_PARAM_SCHEDULE + idx, schedules.get(idx).longValue()); channelStr += "CH=" + ((val & 0XFF0000) >> 16) + "-PR=" + ((val & 0XFF00) >> 8) + " "; } alarmIntent.putExtra(EXTRA_PARAM_TIME, ts); PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT); AlarmManager alarmManager = (AlarmManager) context.getSystemService(ALARM_SERVICE); long currentTimeMillis = System.currentTimeMillis(); Date date = new Date(currentTimeMillis + timeout); String dateStr = (String) DateFormat.format("MM-dd kk:mm:ss", date); Log.d(TAG, "PhotoTimer Reg: " + dateStr + " currentTimeMillis=" + currentTimeMillis + " timeout=" + timeout + " Channels=" + channelStr); alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + timeout, pendingIntent); } private void registerPhotoTimer(int channel, int preset, long ts, long timeout, List schedules) { registerPhotoTimer(this.getApplicationContext(), channel, preset, ts, timeout, schedules); } // private HashMap mTimers = new HashMap(); public boolean registerTimer(long uid, int timeout, long times) { // 创建延迟意图 Intent alarmIntent = new Intent(); alarmIntent.setAction(ACTION_TIMEOUT); alarmIntent.putExtra(EXTRA_PARAM_TIMER_UID, uid); alarmIntent.putExtra(EXTRA_PARAM_TIMEOUT, timeout); alarmIntent.putExtra(EXTRA_PARAM_TIMES, times); alarmIntent.putExtra(EXTRA_PARAM_ELASPED_TIMES, 0L); PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT); mTimers.put(Long.valueOf(uid), pendingIntent); return registerTimer(pendingIntent, uid, timeout); } private void setDefaultDataSubId(int subId) { SubscriptionManager subscriptionManager = (SubscriptionManager) getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE); try { Method method = subscriptionManager.getClass().getDeclaredMethod("setDefaultDataSubId", int.class); method.invoke(subscriptionManager, subId); TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); Method method1 = telephonyManager.getClass().getDeclaredMethod("setDataEnabled", boolean.class); method1.invoke(telephonyManager, true); } catch (Exception e) { Log.e(TAG, "wjz debug setDefaultDataSubId: error is " + e.getMessage()); } } private int getDefaultDataSubId() { SubscriptionManager subscriptionManager = (SubscriptionManager) getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE); try { Method method = subscriptionManager.getClass().getDeclaredMethod("getDefaultDataSubscriptionId"); return (int) method.invoke(subscriptionManager); } catch (Exception e) { Log.e(TAG, "wjz debug getDefaultDataSubId: error is " + e.getMessage()); } return 0; } public boolean registerTimer(PendingIntent pendingIntent, long uid, int timeout) { AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE); alarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + timeout, pendingIntent); Log.i(TAG, "RegTimer:" + uid + " timeout=" + timeout); return true; } public boolean unregisterTimer(long uid) { Long uidObj = Long.valueOf(uid); PendingIntent pendingIntent = mTimers.get(uidObj); if (pendingIntent != null) { AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE); alarmManager.cancel(pendingIntent); mTimers.remove(uidObj); Log.i(TAG, "UnregTimer:" + uid); } return true; } private boolean registerCaptureSchedule(long timeOfZeroPoint, long secondsOfToday) { long[] photoTimeData = getPhotoTimeData(mNativeHandle); if (photoTimeData == null) { return false; } int cnt = photoTimeData.length; short channel = 0; short preset = 0; int ts = 0; long val = 0L; // int maxDuration = mHeartbeatDuration * 2 / 1000; int maxDuration = 35 * 60 * 1000 + 1000; int currentTs = -1; List schedules = new ArrayList<>(); int offset = 0; for (int day = 0; day < 2; day++, offset += 86400) { for (int idx = 0; idx < cnt; idx++) { val = photoTimeData[idx]; ts = (int) ((val & 0x00FFFFFF00000000L) >> 32) + offset; if (ts < secondsOfToday) { continue; } if ((ts - secondsOfToday) > maxDuration) { break; } if (currentTs == -1) { currentTs = ts; channel = (short) ((val & 0xFF0000L) >> 16); preset = (short) ((val & 0xFF00L) >> 8); schedules.add(Long.valueOf(val)); Log.i(TAG, "PhotoTimer Reg: CH=" + channel + " PR=" + preset); } else if (ts > currentTs) { break; } else { channel = (short) ((val & 0xFF0000L) >> 16); preset = (short) ((val & 0xFF00L) >> 8); Log.i(TAG, "PhotoTimer Reg: CH=" + channel + " PR=" + preset); schedules.add(Long.valueOf(val)); } } if (!schedules.isEmpty()) { break; } } if (!schedules.isEmpty()) { long expectedTs = timeOfZeroPoint + ts; // Date date = new Date(expectedTs * 1000); // Log.d(TAG, "Register Photo Time: " + date.toString() + " BaseTime=" + secondsOfToday + " ts=" + ts + " startTime=" + startTime + " expectedTs=" + expectedTs); registerPhotoTimer(channel, preset, expectedTs, expectedTs * 1000 - System.currentTimeMillis(), schedules); } return true; } public static void takePhoto(Context context, int channel, int preset, boolean photoOrVideo) { List schedules = new ArrayList<>(); long ts = System.currentTimeMillis() / 1000; // long val = (ts << 24); long val = 0; val |= ((long)channel << 16); val |= ((long)preset << 8); schedules.add(Long.valueOf(val)); registerPhotoTimer(context, channel, preset, 0, 0, schedules); } @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()); if (intent.hasExtra("messenger")) { mMessenger = intent.getParcelableExtra("messenger"); } String appPath = buildAppDir(this.getApplicationContext()); String ip = intent.getStringExtra("server"); int port = intent.getIntExtra("port", 0); String cmdid = intent.getStringExtra("cmdid"); int protocol = intent.getIntExtra("protocol", 0); int networkProtocol = intent.getIntExtra("networkProtocol", 0); Log.i(TAG, "AppPath=" + appPath + " Server=" + ip + ":" + port + " cmdid=" + cmdid + " Protocol=" + protocol + " Network=" + networkProtocol); MicroPhotoService service = MicroPhotoService.this; service.mNativeHandle = init(appPath, ip, port, cmdid, protocol, networkProtocol); if (service.mNativeHandle !=0) { service.mCmdid = cmdid; Date date = new Date(); long nowTs = date.getTime() / 1000; date.setHours(0); date.setMinutes(0); date.setSeconds(0); long startTime = date.getTime() / 1000; long baseTime = nowTs - startTime; service.registerCaptureSchedule(startTime, baseTime); // AppMaster appMaster = new AppMaster(this, cmdid); // appMaster.start(); } break; case ACTION_STOP: unregisterReceiver(mScreenaAtionReceiver); stopForeground(true); stopSelf(); break; default: stopForeground(true); stopSelf(); } return START_NOT_STICKY; } public void requestWakelock(String name, long timeout) { PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE); PowerManager.WakeLock wl = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK/* | PowerManager.ON_AFTER_RELEASE*/, name); PowerManager.WakeLock wl2 = null; synchronized (mWakeLocks) { wl2 = mWakeLocks.get(name); mWakeLocks.put(name, wl); } if (wl2 != null) { Log.i(TAG, "Release same name wakelock:" + name); wl2.release(); } Log.i(TAG, "Request wakelock:" + name); if (timeout == 0) wl.acquire(); else wl.acquire(timeout); } public void releaseWakelock(String name) { PowerManager.WakeLock wl = null; synchronized (mWakeLocks) { wl = mWakeLocks.get(name); mWakeLocks.remove(name); } if (wl != null) { Log.i(TAG, "Release wakelock:" + name); wl.release(); } } 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, MicroPhotoService.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 static String buildAppDir(Context contxt) { /* File[] paths = contxt.getExternalFilesDirs(null); if (paths == null || paths.length == 0) { return null; } File path = paths[0]; */ File path = new File(Environment.getExternalStorageDirectory(), contxt.getPackageName() + "/"); if (!path.exists() && !path.mkdirs()) { return null; } String p = path.getAbsolutePath(); if (!p.endsWith(File.separator)) { p += File.separator; } return p; } public static String buildPhotoDir(Context contxt, int channel) { // File path = new File(Environment.getExternalStorageDirectory(), "com.xinyingpower.mp/photos/"); String appDir = buildAppDir(contxt); if (appDir == null) { return null; } File path = new File(appDir, "photos/"); if (!path.exists() && !path.mkdirs()) { return null; } String p = path.getAbsolutePath(); if (!p.endsWith(File.separator)) { p += File.separator; } return p; } private String buildPhotoFileName(int channel, int preset, long ts) { LocalDateTime nowDT = LocalDateTime.now(); String date = nowDT.format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss.S")); String photoFile = "img_" + Integer.toString(channel) + "_" + Integer.toHexString(preset).toUpperCase() + "_" + date + ".jpg"; return photoFile; } public boolean updateTime(long timeInMillis) { try { SysApi.setSystemTime(getApplicationContext(), timeInMillis); } catch (Exception ex) { } return true; } public static Uri getUriForFile(Context context, File file) { if (Build.VERSION.SDK_INT > 24) { return FileProvider.getUriForFile(context, context.getPackageName() + ".fileProvider", file); } return Uri.fromFile(file); } public boolean requestPosition() { try { if (mLocationManager == null) { mLocationManager = (LocationManager) getSystemService (Context.LOCATION_SERVICE); if (!mLocationManager.isProviderEnabled(GPS_LOCATION_NAME)) { return false; } mLocateType = mLocationManager.GPS_PROVIDER; } Location location = mLocationManager.getLastKnownLocation(mLocateType); if (location != null) { updatePosition(mNativeHandle, location.getLongitude(), location.getLatitude(), location.getTime()); } // Set Listener mLocationManager.requestLocationUpdates(mLocateType, 100,0, locationListener); return true; } catch (SecurityException ex) { } return false; } public void downloadAndInstall(final String url) { final Context context = getApplicationContext(); final String tempPath = 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); wl.release(); } }); 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 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 = 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 = getPackageManager().getLaunchIntentForPackage(getApplication().getPackageName()); LaunchIntent.putExtra("noDelay", 1); LaunchIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(LaunchIntent); } else { Log.w(TAG, "Recv REBOOT command"); SysApi.reboot(getApplicationContext()); } } }; mHander.postDelayed(runnable, 1000); } public void enableGps(boolean enabled) { SysApi.enableGps(getApplicationContext(), enabled); } public void selectSimCard(int num) { SysApi.selectSimCard4Data(getApplicationContext(), num); } /* TelephonyManager telephonyManager = (TelephonyManager)this.getSystemService(Context.TELEPHONY_SERVICE); // for example value of first element CellInfoGsm cellInfoGsm = (CellInfoGsm)telephonyManager.getAllCellInfo().get(0); CellSignalStrengthGsm cellSignalStrengthGsm = cellInfoGsm.getCellSignalStrength(); cellSignalStrengthGsm.getDbm(); */ protected native long init(String appPath, String ip, int port, String cmdid, int protocol, int networkProtocl); protected native long getHeartbeatDuration(long handler); protected native long[] getPhotoTimeData(long handler); // protected native long[] getNextScheduleItem(long handler); protected native boolean notifyToTakePhoto(long handler, int channel, int preset, long scheduleTime, String path, String fileName, boolean sendToCma); protected native boolean sendHeartbeat(long handler); protected native boolean fireTimeout(long handler, long uid, long times); protected native void updatePosition(long handler, double lon, double lat, long ts); protected native boolean uninit(long handler); ////////////////////////GPS//////////////////// private static final String GPS_LOCATION_NAME = android.location.LocationManager.GPS_PROVIDER; private LocationManager mLocationManager; private String mLocateType; private LocationListener locationListener = new LocationListener() { @Override public void onLocationChanged(Location location) { updatePosition(mNativeHandle, location.getLongitude(), location.getLatitude(), location.getTime()); // Log.i(TAG, "Time: " + location.getTime()); // Log.i(TAG, "经度:" + location.getLongitude()); // Log.i(TAG, "纬度:" + location.getLatitude()); // Log.i(TAG, "海拔:" + location.getAltitude()); } @Override public void onStatusChanged(String provider, int status, Bundle extras) { switch (status) { case LocationProvider.AVAILABLE: // Toast.makeText(MainActivity.this, "onStatusChanged:当前GPS状态为可见状态", Toast.LENGTH_SHORT).show(); break; case LocationProvider.OUT_OF_SERVICE: // Toast.makeText(MainActivity.this, "onStatusChanged:当前GPS状态为服务区外状态", Toast.LENGTH_SHORT).show(); break; case LocationProvider.TEMPORARILY_UNAVAILABLE: // Toast.makeText(MainActivity.this, "onStatusChanged:当前GPS状态为暂停服务状态", Toast.LENGTH_SHORT).show(); break; } } /** * @param provider */ @Override public void onProviderEnabled(String provider) { // Toast.makeText(MainActivity.this, "onProviderEnabled:方法被触发", Toast.LENGTH_SHORT).show(); requestPosition(); } /** * @param provider */ @Override public void onProviderDisabled(String provider) { } protected void writeLog(String log) { if (mMessenger != null) { Message msg = Message.obtain(); msg.what = MSG_WHAT_LOG; msg.obj = log; try { mMessenger.send(msg); } catch (RemoteException e) { e.printStackTrace(); } } } }; ////////////////////////GPS//////////////////// }