From e01802dab928dc7ddb9e247f3a6aff1677dc32ee Mon Sep 17 00:00:00 2001 From: Matthew Date: Mon, 30 Oct 2023 18:00:32 +0800 Subject: [PATCH] =?UTF-8?q?=E6=98=BE=E7=A4=BA=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/cpp/MicroPhoto.cpp | 77 ++++++++-- .../java/com/xypower/mpapp/MainActivity.java | 139 +++++++++++++++++- .../com/xypower/mpapp/MicroPhotoService.java | 29 +++- .../com/xypower/mpapp/utils/RandomReader.java | 79 ++++++++++ 4 files changed, 302 insertions(+), 22 deletions(-) create mode 100644 app/src/main/java/com/xypower/mpapp/utils/RandomReader.java diff --git a/app/src/main/cpp/MicroPhoto.cpp b/app/src/main/cpp/MicroPhoto.cpp index 69394f39..8353f1ab 100644 --- a/app/src/main/cpp/MicroPhoto.cpp +++ b/app/src/main/cpp/MicroPhoto.cpp @@ -32,6 +32,70 @@ bool DumpCallback(const google_breakpad::MinidumpDescriptor& descriptor, } #endif + +static jmethodID mRegisterTimerMid = 0; +static jmethodID mRegisterHeartbeatMid = 0; +static jmethodID mUnregisterTimerMid = 0; +static jmethodID mUpdateTimeMid = 0; + +static jmethodID mRequestWakelockMid = 0; +static jmethodID mReleaseWakelockMid = 0; + +static jmethodID mGetSystemInfoMid = 0; + +static jmethodID mRebootMid = 0; +static jmethodID mEnableGpsMid = 0; +static jmethodID mRequestPositionMid = 0; + +static jmethodID mWriteLogMid = 0; + +jint JNI_OnLoad(JavaVM* vm, void* reserved) +{ + JNIEnv* env = NULL; + jint result = -1; + +#if defined(JNI_VERSION_1_6) + if (result==-1 && vm->GetEnv((void**)&env, JNI_VERSION_1_6) == JNI_OK) + { + result = JNI_VERSION_1_6; + } +#endif +#if defined(JNI_VERSION_1_4) + if (result==-1 && vm->GetEnv((void**)&env, JNI_VERSION_1_4) == JNI_OK) + { + result = JNI_VERSION_1_4; + } +#endif +#if defined(JNI_VERSION_1_2) + if (result==-1 && vm->GetEnv((void**)&env, JNI_VERSION_1_2) == JNI_OK) + { + result = JNI_VERSION_1_2; + } +#endif + + if(result == -1 || env == NULL) + { + return JNI_FALSE; + } + +#ifdef USING_BREAK_PAD + google_breakpad::MinidumpDescriptor descriptor("/sdcard/Android/data/com.xypower.mpapp/files/logs/"); + google_breakpad::ExceptionHandler eh(descriptor, NULL, DumpCallback, NULL, true, -1); +#endif + + + const char* className = "com/xypower/mpapp/MicroPhotoService"; + + jclass clazz = (env)->FindClass(className); + // if((env)->RegisterNatives(clazz, gMethods, 1)< 0) { + // return -1; + // } + + env->DeleteLocalRef(clazz); + + return result; +} + bool GetJniEnv(JavaVM *vm, JNIEnv **env, bool& didAttachThread) { didAttachThread = false; @@ -54,19 +118,6 @@ bool GetJniEnv(JavaVM *vm, JNIEnv **env, bool& didAttachThread) return get_env_result == JNI_OK; } -JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) { - JNIEnv* env; - if (vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6) != JNI_OK) { - return JNI_ERR; - } - -#ifdef USING_BREAK_PAD - google_breakpad::MinidumpDescriptor descriptor("/sdcard/Android/data/com.xypower.mpapp/files/logs/"); - google_breakpad::ExceptionHandler eh(descriptor, NULL, DumpCallback, - NULL, true, -1); -#endif - return JNI_VERSION_1_6; -} extern "C" JNIEXPORT jstring JNICALL Java_com_xypower_mpapp_MainActivity_stringFromJNI( diff --git a/app/src/main/java/com/xypower/mpapp/MainActivity.java b/app/src/main/java/com/xypower/mpapp/MainActivity.java index b3b82f1e..93bb377f 100644 --- a/app/src/main/java/com/xypower/mpapp/MainActivity.java +++ b/app/src/main/java/com/xypower/mpapp/MainActivity.java @@ -11,9 +11,14 @@ import android.location.LocationListener; import android.location.LocationManager; import android.os.Build; import android.os.Environment; +import android.os.FileObserver; import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.os.Messenger; import android.os.SystemClock; +import androidx.annotation.NonNull; import androidx.appcompat.app.ActionBar; import androidx.core.app.ActivityCompat; import androidx.appcompat.app.AppCompatActivity; @@ -22,6 +27,7 @@ import android.os.Bundle; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.text.TextUtils; +import android.text.method.ScrollingMovementMethod; import android.util.Log; import android.view.Display; import android.view.View; @@ -31,6 +37,7 @@ import android.widget.Toast; import com.dev.devapi.api.SysApi; import com.dowse.camera.client.DSCameraManager; import com.xypower.mpapp.databinding.ActivityMainBinding; +import com.xypower.mpapp.utils.RandomReader; //import com.xinyingpower.microphoto.request.INettyMessageListener; //import com.xinyingpower.microphoto.request.NettyChatClient; @@ -53,6 +60,8 @@ public class MainActivity extends AppCompatActivity { public static final String TAG = "MainActivity"; private static int MY_PERMISSIONS_REQUEST_FOREGROUND_SERVICE = 100; + public static final int MSG_WHAT_LOG_OBSERVER = MicroPhotoService.MSG_WHAT_MAX + 10; + public final static int DEFAULT_PROTOCOL = 0xFF00; // Used to load the 'microphoto' library on application startup. @@ -63,8 +72,53 @@ public class MainActivity extends AppCompatActivity { private ActivityMainBinding binding; private int defaultDataSubId; + private Handler mHandler = null; + private Messenger mMessenger = null; + + private LogFileObserver mLogFileObserver = null; + + private class LogFileObserver extends FileObserver { + + private long mOffset = 0; + private String mPath = null; + public LogFileObserver(String path) { + super(path, FileObserver.MODIFY | FileObserver.CREATE); + + mPath = path; + File file = new File(path); + if (file.exists()) { + mOffset = file.length(); + } + } + @Override + public void onEvent(int event, String s) { + int e = event & FileObserver.ALL_EVENTS; + if (e == FileObserver.MODIFY) { + File file = new File(mPath); + long newOffset = file.length(); + if (newOffset > mOffset) { + RandomReader reader = new RandomReader(mPath, mOffset); + + byte[] bytes = new byte[(int)(newOffset - mOffset)]; + int bytesRead = reader.read(bytes); + mOffset += bytesRead; + + Message msg = Message.obtain(); + msg.what = MSG_WHAT_LOG_OBSERVER; + msg.obj = bytes; + msg.arg1 = bytesRead; + mHandler.sendMessage(msg); + } + } + } + } + + @Override protected void onDestroy() { + if (mLogFileObserver != null) { + mLogFileObserver.stopWatching(); + } super.onDestroy(); } @@ -88,6 +142,69 @@ public class MainActivity extends AppCompatActivity { actionBar.setTitle(actionBar.getTitle().toString() + " " + getVersionName(getApplicationContext())); + binding.logs.setText(""); + binding.logs.setMovementMethod(ScrollingMovementMethod.getInstance()); + binding.logs.setScrollbarFadingEnabled(false); + + mHandler = new Handler(Looper.myLooper()) { + @Override + public void handleMessage(@NonNull Message msg) { + switch (msg.what) { + case MicroPhotoService.MSG_WHAT_LOG: { + String log = (String) msg.obj; + binding.logs.append(log); + + // Reply + // Messenger clientMessenger = msg.replyTo; + // Message replyMessage = Message.obtain(null, 2); + // 设置回复消息中的数据 + Bundle replyData = new Bundle(); + replyData.putString("key", "reply value"); + // replyMessage.setData(replyData); + /* + try { + clientMessenger.send(replyMessage); + } catch (RemoteException e) { + e.printStackTrace(); + } + + */ + } + break; + case MSG_WHAT_LOG_OBSERVER: + { + byte[] bytes = (byte[])msg.obj; + int bytesRead = msg.arg1; + String log = null; + try { + log = new String(bytes, 0, bytesRead, "UTF-8"); + } catch (Exception e) { + } + if (log != null) { + binding.logs.append(log); + + int line = binding.logs.getLineCount(); + // if (line > 9) {//超出屏幕自动滚动显示(9是当前页面显示的最大行数) + int offset = line * binding.logs.getLineHeight(); + if (offset > binding.logs.getHeight()) { + binding.logs.scrollTo(0, offset - binding.logs.getHeight() + binding.logs.getLineHeight()); + } + // } + } + } + break; + + } + + } + }; + mMessenger = new Messenger(new Handler()); + + String logFilePath = MicroPhotoService.buildAppDir(this.getApplicationContext()); + logFilePath += "logs/log.txt"; + mLogFileObserver = new LogFileObserver(logFilePath); + mLogFileObserver.startWatching(); + WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE); Display defaultDisplay = windowManager.getDefaultDisplay(); int width = defaultDisplay.getWidth(); @@ -159,6 +276,7 @@ public class MainActivity extends AppCompatActivity { intent.putExtra("port", curAppConfig.port); intent.putExtra("protocol", curAppConfig.protocol); intent.putExtra("networkProtocol", curAppConfig.networkProtocol); + intent.putExtra("messenger", mMessenger); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { MainActivity.this.startForegroundService(intent); @@ -400,15 +518,15 @@ public class MainActivity extends AppCompatActivity { String appPath = MicroPhotoService.buildAppDir(this.getApplicationContext()); InputStreamReader inputStreamReader = null; + BufferedReader bufferedReader = null; try { inputStreamReader = new InputStreamReader(new FileInputStream(new File(appPath + "data/App.json")), "UTF-8"); - BufferedReader bufferedReader = new BufferedReader(inputStreamReader); + bufferedReader = new BufferedReader(inputStreamReader); String line; StringBuilder stringBuilder = new StringBuilder(); while ((line = bufferedReader.readLine()) != null) { stringBuilder.append(line); } - bufferedReader.close(); JSONObject jsonObject = new JSONObject(stringBuilder.toString()); appConfig.cmdid = jsonObject.getString("CMDID"); @@ -427,12 +545,17 @@ public class MainActivity extends AppCompatActivity { } catch (JSONException e) { e.printStackTrace(); } finally { + if (bufferedReader != null) { + try { + bufferedReader.close(); + } catch (Exception ex) { + } + } if (inputStreamReader != null) { try { inputStreamReader.close(); } catch (Exception ex) { } - } } @@ -443,6 +566,7 @@ public class MainActivity extends AppCompatActivity { String appPath = MicroPhotoService.buildAppDir(this.getApplicationContext()); InputStreamReader inputStreamReader = null; + BufferedReader bufferedReader = null; OutputStreamWriter outputStreamWriter = null; try { @@ -452,13 +576,12 @@ public class MainActivity extends AppCompatActivity { } inputStreamReader = new InputStreamReader(new FileInputStream(new File(appPath + "data/App.json")), "UTF-8"); - BufferedReader bufferedReader = new BufferedReader(inputStreamReader); + bufferedReader = new BufferedReader(inputStreamReader); String line; StringBuilder stringBuilder = new StringBuilder(); while ((line = bufferedReader.readLine()) != null) { stringBuilder.append(line); } - bufferedReader.close(); JSONObject jsonObject = new JSONObject(stringBuilder.toString()); @@ -477,6 +600,12 @@ public class MainActivity extends AppCompatActivity { } catch (JSONException e) { e.printStackTrace(); } finally { + if (bufferedReader != null) { + try { + bufferedReader.close(); + } catch (Exception ex) { + } + } if (inputStreamReader != null) { try { inputStreamReader.close(); diff --git a/app/src/main/java/com/xypower/mpapp/MicroPhotoService.java b/app/src/main/java/com/xypower/mpapp/MicroPhotoService.java index 7b64c8bd..8093fa24 100644 --- a/app/src/main/java/com/xypower/mpapp/MicroPhotoService.java +++ b/app/src/main/java/com/xypower/mpapp/MicroPhotoService.java @@ -25,6 +25,7 @@ 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; @@ -58,6 +59,15 @@ public class MicroPhotoService extends Service { 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 String ACTION_START = "ACT_START"; @@ -86,7 +96,6 @@ public class MicroPhotoService extends Service { } private static int mStateService = STATE_SERVICE.NOT_CONNECTED; - public final static int MSG_WHAT_NETWORK_CHANGE = 10; private String mCmdid = ""; private NotificationManager mNotificationManager; @@ -119,7 +128,6 @@ public class MicroPhotoService extends Service { super.onCreate(); mHander = new ServiceHandler(); - mMessenger = new Messenger(mHander); mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); mStateService = STATE_SERVICE.NOT_CONNECTED; @@ -504,8 +512,8 @@ public class MicroPhotoService extends Service { connect(); registerReceiver(mScreenaAtionReceiver, mScreenaAtionReceiver.getFilter()); + mMessenger = intent.getParcelableExtra("messenger"); - // File path = getApplicationContext().getFilesDir(); String appPath = buildAppDir(this.getApplicationContext()); String ip = intent.getStringExtra("server"); @@ -514,7 +522,7 @@ public class MicroPhotoService extends Service { 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); + 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); @@ -940,6 +948,19 @@ cellSignalStrengthGsm.getDbm(); 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//////////////////// diff --git a/app/src/main/java/com/xypower/mpapp/utils/RandomReader.java b/app/src/main/java/com/xypower/mpapp/utils/RandomReader.java new file mode 100644 index 00000000..b3353ff6 --- /dev/null +++ b/app/src/main/java/com/xypower/mpapp/utils/RandomReader.java @@ -0,0 +1,79 @@ +package com.xypower.mpapp.utils; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.RandomAccessFile; + +public class RandomReader { + + protected String fileName; + + protected RandomAccessFile seeker; + + /** Constructor: save filename, construct RandomAccessFile */ + public RandomReader(String fname, long offset) { + fileName = fname; + try { + seeker = new RandomAccessFile(fname, "r"); + if (seeker != null) { + seeker.seek(offset); + } + } catch (Exception e) { + } + } + + @Override + public void finalize() { + if (seeker != null) { + try { + seeker.close(); + } catch (Exception e) { + } + } + } + + public void close() { + if (seeker != null) { + try { + seeker.close(); + } catch (Exception e) { + } + } + } + + /** Read the message at the given offset */ + public String readLine() { + + String line = null; + try { + if (seeker != null) { + line = seeker.readLine(); + } + } catch (Exception e) { + + } + return line; + } + + public int read(byte[] bytes) { + int bytesRead = 0; + try { + if (seeker != null) { + bytesRead = seeker.read(bytes); + } + } catch (Exception e) { + } + return bytesRead; + } + + public long getOffset() { + long offset = 0; + try { + offset = seeker.getChannel().position(); + } catch (Exception e) { + + } + return offset; + } + +}