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.ComponentName; 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.Network; import android.net.NetworkCapabilities; import android.net.NetworkInfo; import android.net.NetworkRequest; import android.net.Uri; import android.net.wifi.WifiManager; import android.os.BatteryManager; import android.os.Build; import android.os.Bundle; 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 androidx.localbroadcastmanager.content.LocalBroadcastManager; 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 com.xypower.common.InetAddressUtils; import com.xypower.common.MicroPhotoContext; import com.xypower.mpapp.v2.Camera2VideoActivity; import java.io.File; import java.lang.reflect.Method; import java.net.InetAddress; 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_SENDING_HB = 40; public final static int MSG_WHAT_MAX = 1000; 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.mpapp.ACT_START"; public static final String ACTION_STOP = "com.xypower.mpapp.ACT_STOP"; public static final String ACTION_RESTART = "com.xypower.mpapp.ACT_RESTART"; public static final String ACTION_MAIN = "com.xypower.mpapp.ACT_MAIN"; private static final String ACTION_HEARTBEAT = MicroPhotoContext.ACTION_HEARTBEAT_MP; private static final String ACTION_TAKE_PHOTO = "com.xypower.mpapp.ACT_TP"; private static final String ACTION_GPS_TIMEOUT = "com.xypower.mpapp.GPS_TIMEOUT"; private static final String ACTION_IMP_PUBKRY = "com.xypower.mpapp.ACT_IMP_PUBKEY"; private static final String ACTION_TAKE_PHOTO_MANUALLY = "com.xypower.mpapp.ACT_TP_M"; private static final String ACTION_HEARTBEAT_MANUALLY = "com.xypower.mpapp.ACT_HB_M"; private static final String ACTION_UPDATE_CONFIGS = "com.xypower.mpapp.ACT_UPD_CFG"; public static final String ACTION_VIDEO_FINISHED = "com.xypower.mpapp.ACT_V_FINISHED"; 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_TAKING_TIME = "TakingTime"; private static final String EXTRA_PARAM_TIME = "Time"; // private static final String EXTRA_PARAM_TIMER_UID = "TimerUid"; // 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 = "fg_mpapp"; 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; // MUST BE 0!!! // private long mNextHeartbeatTime = 0; // private final Map mTimers = new HashMap<>(); protected long mNativeHandle = 0; private AlarmReceiver mAlarmReceiver = null; private AlarmReceiver mLocalMsgReceiver = null; private ScreenActionReceiver mScreenaAtionReceiver = null; private NetworkChangedReceiver mNetworkChangedReceiver = null; private long mGpsTimeout = 60000; // 1 minute private PendingIntent mPreviousGpsTimer = null; private ServiceHandler mHander = null; private Messenger mMessenger = null; private String mModelName = null; public static boolean isRunning = false; private Runnable delayedSleep = new Runnable() { @Override public void run() { Log.i(TAG, "Device Sleep"); // SysApi.sleep(getApplicationContext()); } }; 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_UPDATE_CONFIGS); intentFilter.addAction(ACTION_IMP_PUBKRY); intentFilter.addAction(ACTION_TAKE_PHOTO_MANUALLY); intentFilter.addAction(ACTION_GPS_TIMEOUT); intentFilter.addAction(ACTION_RESTART); // intentFilter.addAction(ACTION_HEARTBEAT_MANUALLY); // intentFilter.addAction(ACTION_MSG_BROADCAST); // intentFilter.addAction(ACTION_VIDEO_FINISHED); // intentFilter.addAction(ACTION_STOP); // intentFilter.addCategory(Intent.CATEGORY_DEFAULT); getApplicationContext().registerReceiver(mAlarmReceiver, intentFilter, Context.RECEIVER_EXPORTED | Context.RECEIVER_VISIBLE_TO_INSTANT_APPS); // IntentFilter intentFilter2 = new IntentFilter(ACTION_MSG_BROADCAST); // registerReceiver(mAlarmReceiver, intentFilter2); // registerRe } { mLocalMsgReceiver = new AlarmReceiver(this); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(ACTION_HEARTBEAT); intentFilter.addAction(ACTION_TAKE_PHOTO); intentFilter.addAction(ACTION_TAKE_PHOTO_MANUALLY); intentFilter.addAction(ACTION_HEARTBEAT_MANUALLY); intentFilter.addAction(ACTION_MSG_BROADCAST); intentFilter.addAction(ACTION_VIDEO_FINISHED); intentFilter.addAction(ACTION_STOP); intentFilter.addAction(ACTION_UPDATE_CONFIGS); LocalBroadcastManager.getInstance(getApplicationContext()).registerReceiver (mLocalMsgReceiver, 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); getApplicationContext().registerReceiver(mNetworkChangedReceiver, filter); } AlarmManager alarmManager = (AlarmManager) getApplicationContext().getSystemService(ALARM_SERVICE); while (true) { AlarmManager.AlarmClockInfo aci = alarmManager.getNextAlarmClock(); if (aci == null) { break; } } enableGps(true); requestPosition(); } @Override public void onDestroy() { mStateService = STATE_SERVICE.NOT_CONNECTED; Log.w(TAG, "MicroPhotoService::onDestroy called"); if (mNativeHandle != 0) { uninit(mNativeHandle); mNativeHandle = 0; isRunning = false; } getApplicationContext().unregisterReceiver(mAlarmReceiver); getApplicationContext().unregisterReceiver(mScreenaAtionReceiver); getApplicationContext().unregisterReceiver(mNetworkChangedReceiver); LocalBroadcastManager.getInstance(getApplicationContext()).unregisterReceiver(mLocalMsgReceiver); for(Map.Entry entry : mWakeLocks.entrySet()) { try { PowerManager.WakeLock wl = entry.getValue(); wl.setReferenceCounted(false); wl.release(); wl = null; } catch (Exception ex) { ex.printStackTrace(); } } 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 void sendMessage(Context context, int what, int data) { Intent intent = new Intent(ACTION_MSG_BROADCAST); intent.putExtra("what", what); intent.putExtra("data", data); intent.setPackage(context.getPackageName()); String typeName = AlarmReceiver.class.getTypeName(); intent.setComponent( new ComponentName(context.getPackageName(), AlarmReceiver.class.getTypeName()) ); context.sendBroadcast(intent); } 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); Runnable runnable = new Runnable() { public void run() { mService.sendHeartbeat(mService.mNativeHandle, mService.getSignalLevel()); } }; Thread th = new Thread(runnable); th.start(); mService.registerHeartbeatTimer(); try { ConnectivityManager connectivityManager = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE); if (connectivityManager != null) { if (!connectivityManager.isDefaultNetworkActive()) { infoLog("DefaultNetwork is NOT Active"); } } } catch (Exception ex) { } } 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); boolean photoOrVideo = ((val & 0xFFL) == 0); Log.i(TAG, "PhotoTimer Fired: CH=" + channel + " PR=" + preset); mService.notifyToTakePhoto(mService.mNativeHandle, channel, preset, ts, photoOrVideo); } } // Register Next Photo Timer Date date = new Date(); long startTime = (date.getTime() + 999) / 1000 + 1; // Add one second mService.updateCaptureSchedule(startTime); } else if (TextUtils.equals(ACTION_HEARTBEAT_MANUALLY, action)) { Log.i(TAG, "HB Timer Fired ACTION=" + action); mService.sendHeartbeat(mService.mNativeHandle, mService.getSignalLevel()); } else if (TextUtils.equals(ACTION_TAKE_PHOTO_MANUALLY, action)) { int channel = intent.getIntExtra(EXTRA_PARAM_CHANNEL, 0); int preset = intent.getIntExtra(EXTRA_PARAM_PRESET, 0xFF); // 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, photoOrVideo); } else if (TextUtils.equals(ACTION_MSG_BROADCAST, action)) { int what = intent.getIntExtra("what", 0); int data = intent.getIntExtra("data", 0); if (what == MSG_WHAT_SENDING_HB) { mService.sendHeartbeat(mService.mNativeHandle, mService.getSignalLevel()); } } else if (TextUtils.equals(ACTION_UPDATE_CONFIGS, action)) { int restart = intent.getIntExtra("restart", 0); Log.i(TAG, "UPD CFG Fired ACTION=" + action + " restart=" + restart); if (restart != 0) { MicroPhotoService.restartApp(context, context.getPackageName()); } else if (mService.mNativeHandle != 0) { mService.reloadConfigs(mService.mNativeHandle); } } else if (TextUtils.equals(ACTION_VIDEO_FINISHED, action)) { boolean result = intent.getBooleanExtra("result", false); String path = intent.getStringExtra("path"); long videoId = intent.getLongExtra("videoId", 0); Log.i(TAG, "Recording received(" + Long.toString(videoId) + "):" + path); mService.recordingFinished(mService.mNativeHandle, result, path, videoId); } else if (TextUtils.equals(ACTION_STOP, action)) { mService.stopTerminalService(); } else if (TextUtils.equals(ACTION_IMP_PUBKRY, action)) { String path = intent.getStringExtra("path"); String md5 = intent.getStringExtra("md5"); } else if (TextUtils.equals(ACTION_GPS_TIMEOUT, action)) { mService.mPreviousGpsTimer = null; try { mService.mLocationManager.removeUpdates(mService.mLocationListener); } catch (Exception ex) { ex.printStackTrace(); } mService.enableGps(false); } else if (TextUtils.equals(ACTION_RESTART, action)) { MicroPhotoService.restartApp(context.getApplicationContext(), MicroPhotoContext.PACKAGE_NAME_MPAPP); } } } // Will be called fron native private void registerHeartbeatTimer(int duration, long nextPhotoTime) { int orgHeartbeatDuration = mHeartbeatDuration; if (orgHeartbeatDuration == 0) { if (nextPhotoTime == 0) { mHeartbeatDuration = duration; registerHeartbeatTimer(); } else { long ts = System.currentTimeMillis(); nextPhotoTime *= 1000; if (nextPhotoTime > ts) { mHeartbeatDuration = (int) ((nextPhotoTime - ts) % duration) + 999; registerHeartbeatTimer(); mHeartbeatDuration = duration; } else { mHeartbeatDuration = duration; registerHeartbeatTimer(); } } } else { mHeartbeatDuration = duration; } } private void registerHeartbeatTimer() { // 创建延迟意图 Intent alarmIntent = new Intent(); alarmIntent.setAction(ACTION_HEARTBEAT); alarmIntent.putExtra("HeartbeatDuration", mHeartbeatDuration); 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, long scheduleTime, long takingTime, long timeout, List schedules) { // 创建延迟意图 Intent intent = new Intent(); intent.setAction(ACTION_TAKE_PHOTO); int cnt = schedules.size(); intent.putExtra(EXTRA_PARAM_SCHEDULES, cnt); StringBuilder channelStr = new StringBuilder(); long val = 0; for (int idx = 0; idx < cnt; idx++) { val = schedules.get(idx).longValue(); intent.putExtra(EXTRA_PARAM_SCHEDULE + idx, schedules.get(idx).longValue()); channelStr.append("(" + ((val & 0XFF0000) >> 16) + "-" + Long.toString (((val & 0XFF00) >> 8), 16).toUpperCase() + ") "); } intent.putExtra(EXTRA_PARAM_TIME, scheduleTime); intent.putExtra(EXTRA_PARAM_TAKING_TIME, takingTime); if (timeout == 0) { // LocalBroadcast LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(context); localBroadcastManager.sendBroadcast(intent); } else { PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); AlarmManager alarmManager = (AlarmManager) context.getSystemService(ALARM_SERVICE); try { alarmManager.cancel(pendingIntent); } catch (Exception ex) { ex.printStackTrace(); } 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 + " CH-PR=" + channelStr.toString()); alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + timeout, pendingIntent); } } private void registerPhotoTimer(long scheduleTime, long timeout, List schedules) { registerPhotoTimer(getApplicationContext(), scheduleTime, scheduleTime, timeout, schedules); } public void startRecording(int cameraId, long videoId, int duration, int width, int height, int quality, int orientation, String leftTopOsd, String rightTopOsd, String rightBottomOsd, String leftBottomOsd) { Context context = getApplicationContext(); // Intent intent = new Intent(this, VideoActivity.class); Intent intent = makeRecordingIntent(context, cameraId, videoId, duration, width, height, quality, orientation, leftTopOsd, rightTopOsd, rightBottomOsd, leftBottomOsd); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(intent); } public static Intent makeRecordingIntent(Context context, int cameraId, long videoId, int duration, int width, int height, int quality, int orientation, String leftTopOsd, String rightTopOsd, String rightBottomOsd, String leftBottomOsd) { // Intent intent = new Intent(this, VideoActivity.class); Intent intent = new Intent(context, Camera2VideoActivity.class); intent.putExtra("cameraId", cameraId); intent.putExtra("videoId", videoId); intent.putExtra("duration", duration); intent.putExtra("width", width); intent.putExtra("height", height); intent.putExtra("quality", quality); intent.putExtra("orientation", orientation); intent.putExtra("leftTopOsd", leftTopOsd); intent.putExtra("rightTopOsd", rightTopOsd); intent.putExtra("rightBottomOsd", rightBottomOsd); intent.putExtra("leftBottomOsd", leftBottomOsd); // intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); return intent; } protected boolean updateCaptureSchedule(long startTime) { long[] photoTimeData = getPhotoTimeData(mNativeHandle, startTime); if (photoTimeData == null || photoTimeData.length < 4) { return false; } // int maxDuration = 35 * 60 * 1000 + 1000; List schedules = new ArrayList<>(); for (int idx = 0; idx < photoTimeData[2]; idx++) { schedules.add(Long.valueOf(photoTimeData[3 + idx])); } if (schedules.isEmpty()) { return false; } long expectedTs = photoTimeData[0] + photoTimeData[1]; registerPhotoTimer(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); val |= photoOrVideo ? 0L : 1L; schedules.add(Long.valueOf(val)); registerPhotoTimer(context, 0, ts, 0, schedules); } public static void sendHeartbeat(Context context) { Intent intent = new Intent(); intent.setAction(ACTION_HEARTBEAT_MANUALLY); // PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0); LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(context); localBroadcastManager.sendBroadcast(intent); } public static void updateConfigs(Context context) { Intent intent = new Intent(); intent.setAction(ACTION_UPDATE_CONFIGS); // PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0); LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(context); localBroadcastManager.sendBroadcast(intent); } @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(); getApplicationContext().registerReceiver(mScreenaAtionReceiver, mScreenaAtionReceiver.getFilter()); if (intent.hasExtra("messenger")) { mMessenger = intent.getParcelableExtra("messenger"); } int network = intent.getIntExtra("network", 0); network = 0; if (network == 0) { startTerminalService(intent); } else { ConnectivityManager cm =(ConnectivityManager) getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE); NetworkRequest.Builder builder = new NetworkRequest.Builder(); builder.addCapability(NetworkCapabilities.NET_CAPABILITY_DUN); builder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); List availableNetworkInfos = new ArrayList<>(); cm.registerNetworkCallback(builder.build(), new ConnectivityManager.NetworkCallback() { @Override public void onAvailable(Network network) { super.onAvailable(network); availableNetworkInfos.add(cm.getNetworkInfo(network)); Log.i(TAG, "Network"); } }); NetworkInfo[] networkInfos = cm.getAllNetworkInfo(); for (NetworkInfo ni : networkInfos) { if (ni.getType() == ConnectivityManager.TYPE_MOBILE || ni.getType() == ConnectivityManager.TYPE_MOBILE_DUN || ni.getType() == ConnectivityManager.TYPE_WIFI) { // availableNetworkInfos.add(ni); } } Network[] networks = cm.getAllNetworks(); for (Network nw : networks) { NetworkInfo nwi = cm.getNetworkInfo(nw); String name = nwi.toString(); if (name.equals("")) { } } } break; case ACTION_STOP: try { getApplicationContext().unregisterReceiver(mScreenaAtionReceiver); } catch (Exception ex) { } stopForeground(true); stopSelf(); break; default: stopForeground(true); stopSelf(); } return START_NOT_STICKY; } private void startTerminalService(Intent intent) { if (MicroPhotoService.this.mNativeHandle != 0) { return; } final String appPath = MicroPhotoContext.buildAppDir(this.getApplicationContext()); final String server = intent.getStringExtra("server"); final int port = intent.getIntExtra("port", 0); final String cmdid = intent.getStringExtra("cmdid"); final int protocol = intent.getIntExtra("protocol", 0); final int networkProtocol = intent.getIntExtra("networkProtocol", 0); final int encryptData = intent.getIntExtra("encryption", 0); Runnable runnable = new Runnable() { public void run() { String ip = server; if (!InetAddressUtils.isIPv4Address(ip) && !InetAddressUtils.isIPv6Address(ip)) { // It is a domain InetAddress addr = null; try { addr = InetAddress.getByName(server); } catch (Exception e) { e.printStackTrace(); } if (addr != null) { ip = addr.getHostAddress(); } } Log.i(TAG, "AppPath=" + appPath + " Server=" + ip + ":" + port + " cmdid=" + cmdid + " Protocol=" + protocol + " Network=" + networkProtocol); MicroPhotoService service = MicroPhotoService.this; Context context = service.getApplicationContext(); int versionCode = MicroPhotoContext.getVersionCode(context); String simcard = SysApi.getImei(getApplicationContext()); if (simcard == null) { simcard = ""; } String tfCardPath = MicroPhotoContext.getSecondaryStoragePath(context); service.mNativeHandle = init(appPath, server, port, cmdid, protocol, networkProtocol, encryptData, 0, service.getSignalLevel(), versionCode, BuildConfig.BUILD_TIMESTAMP, simcard, tfCardPath); if (service.mNativeHandle != 0) { isRunning = true; service.mCmdid = cmdid; Date date = new Date(); long startTime = (date.getTime() + 999) / 1000; service.updateCaptureSchedule(startTime); if (mPreviousLocation != null) { service.updatePosition(mNativeHandle, mPreviousLocation.getLongitude(), mPreviousLocation.getLatitude(), mPreviousLocation.getAccuracy(), mPreviousLocation.getTime() / 1000); } /* try { Location location = mLocationManager.getLastKnownLocation(mLocateType); if (location != null) { service.updatePosition(service.mNativeHandle, location.getLongitude(), location.getLatitude(), location.getAccuracy(), location.getTime() / 1000); } } catch (Exception ex) { ex.printStackTrace(); } */ } } }; Thread th = new Thread(runnable); th.start(); } public static void stopTerminalService(Context context) { Intent alarmIntent = new Intent(); alarmIntent.setPackage(context.getPackageName()); alarmIntent.setAction(ACTION_STOP); PendingIntent pendingIntent = PendingIntent.getBroadcast(context.getApplicationContext(), 0, alarmIntent, 0); AlarmManager alarmManager = (AlarmManager) context.getApplicationContext().getSystemService(ALARM_SERVICE); alarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 100, pendingIntent); } public void stopTerminalService() { if (mNativeHandle == 0) { return; } Runnable runnable = new Runnable() { public void run() { uninit(mNativeHandle); mNativeHandle = 0; try { getApplicationContext().unregisterReceiver(mScreenaAtionReceiver); } catch (Exception ex) { } stopForeground(true); stopSelf(); } }; Thread thread = new Thread(runnable); thread.start(); } 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); } try { mHander.removeCallbacks(delayedSleep); } catch (Exception ex) { // ex.printStackTrace(); } if (wl2 != null) { Log.i(TAG, "Release same name wakelock:" + name); wl2.setReferenceCounted(false); 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) { try { wl = mWakeLocks.get(name); mWakeLocks.remove(name); if (mWakeLocks.isEmpty()) { // mHander.postDelayed(delayedSleep, 2000); } } catch (Exception ex) { ex.printStackTrace(); } } if (wl != null) { Log.i(TAG, "Release wakelock:" + name); try { final PowerManager.WakeLock finalWl = wl; wl = null; mHander.postDelayed(new Runnable() { @Override public void run() { try { finalWl.setReferenceCounted(false); finalWl.release(); } catch (Exception ex) { ex.printStackTrace(); } } }, 200); } catch (Exception ex) { ex.printStackTrace(); } } } 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(), "MP 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 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(android.location.LocationManager.GPS_PROVIDER)) { return false; } mLocateType = mLocationManager.GPS_PROVIDER; // Set Listener } try { mLocationManager.requestLocationUpdates(mLocateType, 30000, 1, mLocationListener); } catch (Exception ex) { ex.printStackTrace(); } Location location = mLocationManager.getLastKnownLocation(mLocateType); if (location != null && mNativeHandle != 0) { updatePosition(mNativeHandle, location.getLongitude(), location.getLatitude(), location.getAccuracy(), location.getTime() / 1000); } return true; } catch (SecurityException ex) { ex.printStackTrace(); } return false; } 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(); } protected int getSignalLevel() { try { final TelephonyManager telephonyManager = (TelephonyManager) getApplicationContext().getSystemService(Context.TELEPHONY_SERVICE); SignalStrength ss = telephonyManager.getSignalStrength(); if (ss != null) { return ss.getLevel(); } } catch (Exception ex) { } return -1; } 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); } // SysApi.getCpuRate(); return sb.toString(); } public boolean installApp(final String path, long delayedTime) { if (delayedTime < 0) { delayedTime = 0; } final Context context = getApplicationContext(); Runnable runnable = new Runnable() { @Override public void run() { SysApi.installApk(context, path, context.getPackageName(), true); } }; mHander.postDelayed(runnable, delayedTime); return true; } public void reboot(final int rebootType, final long timeout) { Runnable runnable = new Runnable() { @Override public void run() { if (rebootType == 0) { Context context = MicroPhotoService.this.getApplicationContext(); restartApp(context, context.getPackageName()); } else { Log.w(TAG, "Recv REBOOT command"); SysApi.reboot(MicroPhotoService.this.getApplicationContext()); } } }; mHander.postDelayed(runnable, timeout > 0 ? timeout : 1000); } public static void restartApp(Context context, String packageName) { Intent intent = new Intent(context, MainActivity.class); int noDelay = 1; intent.putExtra("noDelay", noDelay); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); context.startActivity(intent); System.exit(0); /* Intent intent = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName()); int noDelay = 1; intent.putExtra("noDelay", noDelay); PendingIntent restartIntent = PendingIntent.getActivity(context, 0, intent, 0); AlarmManager mgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE); mgr.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 500, restartIntent); System.exit(0); */ } public void enableGps(boolean enabled) { if (enabled) { try { AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE); if (mPreviousGpsTimer != null) { alarmManager.cancel(mPreviousGpsTimer); mPreviousGpsTimer = null; } Intent intent = new Intent(); intent.setAction(ACTION_GPS_TIMEOUT); mPreviousGpsTimer = PendingIntent.getBroadcast(this, 0, intent, 0); alarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + mGpsTimeout, mPreviousGpsTimer); } catch (Exception ex) { ex.printStackTrace(); } } else { if (mPreviousGpsTimer != null) { try { AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE); alarmManager.cancel(mPreviousGpsTimer); } catch (Exception ex) { ex.printStackTrace(); } finally { mPreviousGpsTimer = null; } } } SysApi.enableGps(getApplicationContext(), enabled); } /* 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, int encryptData, long netHandle, int signalLevel, int versionCode, long buildTime, String simcard, String tfCardPath); protected native long getHeartbeatDuration(long handler); protected native long[] getPhotoTimeData(long handler, long startTime); protected native long[] getPhotoTimeData2(long handler); // protected native long[] getNextScheduleItem(long handler); protected native boolean notifyToTakePhoto(long handler, int channel, int preset, long scheduleTime, boolean photoOrVideo); protected native boolean sendHeartbeat(long handler, int signalLevel); protected native boolean reloadConfigs(long handler); protected native void updatePosition(long handler, double lon, double lat, double radius, long ts); protected native boolean uninit(long handler); protected native void recordingFinished(long handler, boolean result, String path, long videoId); public static native long takePhoto(int channel, int preset, boolean photoOrVideo, String configFilePath, String path); public static native void releaseDeviceHandle(long deviceHandle); public static native void infoLog(String log); public static native void setOtgState(boolean enabled); public static native void setCam3V3Enable(boolean enabled); public static native String getSerialNumber(); public static native boolean importPublicKeyFile(int index, String outputPath, String md5); public static native boolean importPublicKey(int index, byte cert[]); public static native boolean genKeys(int index); public native static int getGpioInt(int cmd); public static native String querySecVersion(); public static native boolean genCertRequest(int index, int type, String subject, String outputPath); public static native boolean importPrivateKeyFile(int index, String outputPath, String md5); public static native boolean exportPublicKeyFile(int index, String outputPath); public static native boolean exportPrivateFile(int index, String outputPath); ////////////////////////GPS//////////////////// // private static final String GPS_LOCATION_NAME = android.location.LocationManager.GPS_PROVIDER; private LocationManager mLocationManager; private Location mPreviousLocation = null; private String mLocateType; private LocationListener mLocationListener = new LocationListener() { @Override public void onLocationChanged(Location location) { if (mNativeHandle != 0) { updatePosition(mNativeHandle, location.getLongitude(), location.getLatitude(), location.getAccuracy(), location.getTime() / 1000); } else { mPreviousLocation = location; } mLocationManager.removeUpdates(this); // Close GPS enableGps(false); Log.i(TAG, "Time:" + location.getTime() + " Lon=" + location.getLongitude() + "Lat=" + location.getLatitude() + "Alt=" + 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//////////////////// 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; } }