diff --git a/src/main/java/org/qpython/qsl4a/QSL4APP.java b/src/main/java/org/qpython/qsl4a/QSL4APP.java index 49298b450a0c840cf62c1677aeb6d6d7f272ca66..69e3533d74f4492e22abbd69c10680afdb1df38b 100644 --- a/src/main/java/org/qpython/qsl4a/QSL4APP.java +++ b/src/main/java/org/qpython/qsl4a/QSL4APP.java @@ -1,7 +1,5 @@ package org.qpython.qsl4a; -import android.app.Application; - import com.quseit.base.MyApp; import org.qpython.qsl4a.qsl4a.FutureActivityTaskExecutor; diff --git a/src/main/java/org/qpython/qsl4a/qsl4a/facade/AndroidFacade.java b/src/main/java/org/qpython/qsl4a/qsl4a/facade/AndroidFacade.java index a117c70a0df22d8ffdefb991232a6f7e00b6ef9b..d6db9e92f33e6e54ee294c853c390e1b8e43840a 100644 --- a/src/main/java/org/qpython/qsl4a/qsl4a/facade/AndroidFacade.java +++ b/src/main/java/org/qpython/qsl4a/qsl4a/facade/AndroidFacade.java @@ -109,7 +109,11 @@ public class AndroidFacade extends RpcReceiver { private final Resources mResources; private ClipboardManager mClipboard = null; + //乘着船 修改 public final Context context; + public final String qpyProvider; + + private final int intentFlags = Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION ; @Override public void shutdown() { @@ -133,6 +137,7 @@ public class AndroidFacade extends RpcReceiver { mResources = manager.getAndroidFacadeResources(); //乘着船 修改 context = mService.getApplicationContext(); + qpyProvider = context.getPackageName() + ".provider"; } @@ -371,7 +376,7 @@ public class AndroidFacade extends RpcReceiver { void startActivity(final Intent intent) { try { - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.setFlags(intentFlags); context.startActivity(intent); } catch (Exception e) { LogUtil.e("Failed to launch intent.", e); @@ -420,8 +425,9 @@ public class AndroidFacade extends RpcReceiver { return startActivityForResult(intent); } - private void doStartActivity(final Intent intent, Boolean wait) throws Exception { - if (wait == null || wait == false) { + public void doStartActivity(final Intent intent, Boolean wait) throws Exception { + intent.setFlags(intent.getFlags() | intentFlags); + if (wait == null || !wait) { startActivity(intent); } else { FutureActivityTask task = new FutureActivityTask() { @@ -532,15 +538,16 @@ public class AndroidFacade extends RpcReceiver { } @Rpc(description = "Displays a short-duration Toast notification.") - public void makeToast(@RpcParameter(name = "message") final String message) { + public void makeToast(@RpcParameter(name = "message") final String message, + @RpcParameter(name = "length") @RpcDefault("0") final Integer length) { mHandler.post(new Runnable() { - @Override public void run() { - Toast.makeText(mService, message, Toast.LENGTH_SHORT).show(); + Toast.makeText(mService, message, length).show(); } }); } + /* 乘着船:过时删除 private String getInputFromAlertDialog(final String title, final String message, final boolean password) { final FutureActivityTask task = new FutureActivityTask() { @@ -599,7 +606,7 @@ public class AndroidFacade extends RpcReceiver { @RpcParameter(name = "title", description = "title of the input box") @RpcDefault("SL4A Password Input") final String title, @RpcParameter(name = "message", description = "message to display above the input box") @RpcDefault("Please enter password:") final String message) { return getInputFromAlertDialog(title, message, true); - } + }*/ private static int NOTIFICATION_ID = 0x20002;//通知栏消息id diff --git a/src/main/java/org/qpython/qsl4a/qsl4a/facade/CommonIntentsFacade.java b/src/main/java/org/qpython/qsl4a/qsl4a/facade/CommonIntentsFacade.java index 416f975fea571616fe184216767657513e66dbc8..a8aad2dfe2fa55b54c49ee067e86bf5e82a4ca78 100644 --- a/src/main/java/org/qpython/qsl4a/qsl4a/facade/CommonIntentsFacade.java +++ b/src/main/java/org/qpython/qsl4a/qsl4a/facade/CommonIntentsFacade.java @@ -1,13 +1,19 @@ package org.qpython.qsl4a.qsl4a.facade; import android.app.SearchManager; +import android.app.Service; +import android.content.Context; import android.content.Intent; import android.net.Uri; +import android.os.Build; import android.provider.Contacts.People; +import android.support.v4.content.FileProvider; +import android.webkit.MimeTypeMap; import org.qpython.qsl4a.qsl4a.jsonrpc.RpcReceiver; import org.qpython.qsl4a.qsl4a.rpc.Rpc; +import org.qpython.qsl4a.qsl4a.rpc.RpcDefault; import org.qpython.qsl4a.qsl4a.rpc.RpcOptional; import org.qpython.qsl4a.qsl4a.rpc.RpcParameter; @@ -26,10 +32,16 @@ import org.json.JSONObject; public class CommonIntentsFacade extends RpcReceiver { private final AndroidFacade mAndroidFacade; + private final Context context; + private final String qpyProvider; + private final Service mService; public CommonIntentsFacade(FacadeManager manager) { super(manager); mAndroidFacade = manager.getReceiver(AndroidFacade.class); + context = mAndroidFacade.context; + qpyProvider = mAndroidFacade.qpyProvider; + mService = manager.getService(); } @Override @@ -78,12 +90,26 @@ public class CommonIntentsFacade extends RpcReceiver { view(People.CONTENT_URI, null); } - @Rpc(description = "Opens the browser to display a local HTML file.") + @Rpc(description = "Opens the browser to display a local HTML/text/audio/video File or http(s) Website .") public void viewHtml( - @RpcParameter(name = "path", description = "the path to the HTML file") String path) - throws JSONException { - File file = new File(path); - view(Uri.fromFile(file), "text/html"); + @RpcParameter(name = "path", description = "the path to the local HTML/text/audio/video File or http(s) Website") String path, + @RpcParameter(name = "title") @RpcOptional String title, + @RpcParameter(name = "wait") @RpcDefault("true") Boolean wait) + throws Exception { + Uri uri; + Intent intent = new Intent(); + if (path.contains("://")) { + uri=Uri.parse(path); + intent.putExtra("src",path); + } else { + uri=Uri.fromFile(new File(path)); + intent.putExtra("LOG_PATH",path); + } + intent.setClassName(context,"org.qpython.qpy.main.activity.QWebViewActivity"); + intent.setDataAndType(uri, "text/html"); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT|Intent.FLAG_ACTIVITY_MULTIPLE_TASK|Intent.FLAG_ACTIVITY_NEW_TASK); + intent.putExtra("title",title); + mAndroidFacade.doStartActivity(intent,wait); } @Rpc(description = "Starts a search for the given query.") @@ -92,4 +118,56 @@ public class CommonIntentsFacade extends RpcReceiver { intent.putExtra(SearchManager.QUERY, query); mAndroidFacade.startActivity(intent); } + + @Rpc(description = "Convert normal path to content:// or file:// .") + public String pathToUri( + @RpcParameter(name = "path") String path) { + File file = new File(path); + Uri uri; + if (Build.VERSION.SDK_INT>=24) { + uri = FileProvider.getUriForFile(context,qpyProvider,file); + } else { + uri = Uri.fromFile(file); + } + return uri.toString(); + } + + @Rpc(description = "Open a file with path") + public void openFile( + @RpcParameter(name = "path") String path, + @RpcParameter(name = "type", description = "a MIME type of a file") @RpcOptional String type, + @RpcParameter(name = "wait") @RpcDefault("true") Boolean wait) + throws Exception { + MimeTypeMap mime = MimeTypeMap.getSingleton(); + if (type == null) { + /* 获取文件的后缀名 */ + int dotIndex = path.lastIndexOf("."); + if (dotIndex < 0) { + type = "*/*"; //找不到扩展名 + } else { + try { + type = mime.getMimeTypeFromExtension( path.substring( dotIndex + 1 ).toLowerCase() ); + if (type == null) { + type = "*/*"; //找不到打开方式 + } + } catch (Exception e) { + type="*/*"; //出现错误 + } + }} + Intent intent = new Intent(); + intent.setAction(android.content.Intent.ACTION_VIEW); + File file = new File(path); + Uri uri; + if (Build.VERSION.SDK_INT>=24) { + uri = FileProvider.getUriForFile(context,qpyProvider,file); + } else { + uri = Uri.fromFile(file); + } + intent.setDataAndType(uri, type); + try { + mAndroidFacade.doStartActivity(intent,wait); + } catch (Exception e) { + e.printStackTrace(); + } + } } diff --git a/src/main/java/org/qpython/qsl4a/qsl4a/facade/FacadeConfiguration.java b/src/main/java/org/qpython/qsl4a/qsl4a/facade/FacadeConfiguration.java index 81c14180a9b78c11ee186393c4aac0be04531bdb..b9bb0bc322424228ac52f18ba4695465c31fbd8e 100644 --- a/src/main/java/org/qpython/qsl4a/qsl4a/facade/FacadeConfiguration.java +++ b/src/main/java/org/qpython/qsl4a/qsl4a/facade/FacadeConfiguration.java @@ -86,6 +86,7 @@ public class FacadeConfiguration { sFacadeClassList.add(PreferencesFacade.class); sFacadeClassList.add(QPyInterfaceFacade.class); sFacadeClassList.add(USBHostSerialFacade.class); + sFacadeClassList.add(VideoFacade.class); if (sSdkLevel >= 4) { sFacadeClassList.add(TextToSpeechFacade.class); diff --git a/src/main/java/org/qpython/qsl4a/qsl4a/facade/SignalStrengthFacade.java b/src/main/java/org/qpython/qsl4a/qsl4a/facade/SignalStrengthFacade.java index 915454d446f4f3014828b46c704a4109bc1fd11b..17ad2e98742888b5033fe2b87fbf449bbf8ed6c7 100644 --- a/src/main/java/org/qpython/qsl4a/qsl4a/facade/SignalStrengthFacade.java +++ b/src/main/java/org/qpython/qsl4a/qsl4a/facade/SignalStrengthFacade.java @@ -2,6 +2,7 @@ package org.qpython.qsl4a.qsl4a.facade; import android.app.Service; import android.content.Context; +import android.os.Build; import android.os.Bundle; import android.telephony.PhoneStateListener; import android.telephony.SignalStrength; @@ -14,6 +15,7 @@ import org.qpython.qsl4a.qsl4a.rpc.RpcMinSdk; import org.qpython.qsl4a.qsl4a.rpc.RpcStartEvent; import org.qpython.qsl4a.qsl4a.rpc.RpcStopEvent; +import java.lang.reflect.Method; import java.util.concurrent.Callable; /** @@ -35,22 +37,44 @@ public class SignalStrengthFacade extends RpcReceiver { mEventFacade = manager.getReceiver(EventFacade.class); mTelephonyManager = (TelephonyManager) manager.getService().getSystemService(Context.TELEPHONY_SERVICE); - mPhoneStateListener = MainThread.run(mService, new Callable() { + mPhoneStateListener = MainThread.run(mService, (Callable) () -> new PhoneStateListener() { @Override - public PhoneStateListener call() throws Exception { - return new PhoneStateListener() { - @Override - public void onSignalStrengthsChanged(SignalStrength signalStrength) { - mSignalStrengths = new Bundle(); - mSignalStrengths.putInt("gsm_signal_strength", signalStrength.getGsmSignalStrength()); - mSignalStrengths.putInt("gsm_bit_error_rate", signalStrength.getGsmBitErrorRate()); - mSignalStrengths.putInt("cdma_dbm", signalStrength.getCdmaDbm()); - mSignalStrengths.putInt("cdma_ecio", signalStrength.getCdmaEcio()); - mSignalStrengths.putInt("evdo_dbm", signalStrength.getEvdoDbm()); - mSignalStrengths.putInt("evdo_ecio", signalStrength.getEvdoEcio()); - mEventFacade.postEvent("signal_strengths", mSignalStrengths.clone()); - } - }; + //旧版安卓信号强度获取方式 + public void onSignalStrengthsChanged(SignalStrength signalStrength) { + mSignalStrengths = new Bundle(); + mSignalStrengths.putInt("gsm_signal_strength", signalStrength.getGsmSignalStrength()); + mSignalStrengths.putInt("gsm_bit_error_rate", signalStrength.getGsmBitErrorRate()); + mSignalStrengths.putInt("cdma_dbm", signalStrength.getCdmaDbm()); + mSignalStrengths.putInt("cdma_ecio", signalStrength.getCdmaEcio()); + mSignalStrengths.putInt("evdo_dbm", signalStrength.getEvdoDbm()); + mSignalStrengths.putInt("evdo_ecio", signalStrength.getEvdoEcio()); + mSignalStrengths.putInt("evdo_snr", signalStrength.getEvdoSnr()); + Method method; + int dbm,Dbm=Integer.MAX_VALUE; + try { + method = signalStrength.getClass().getMethod("getDbm"); + Dbm = (int) method.invoke(signalStrength); + mSignalStrengths.putInt("dbm", Dbm); + } catch (Exception ignored){} + String[] flags = {"Rsrp","Rsrq","Rssnr"}; + for (String flag : flags){ + try { + method = signalStrength.getClass().getDeclaredMethod("getLte"+flag); + method.setAccessible(true); + dbm = (int) method.invoke(signalStrength); + mSignalStrengths.putInt("lte_"+flag.toLowerCase(),dbm); + } catch (Exception ignored){}} + try { + method = signalStrength.getClass().getDeclaredMethod("getWcdmaEcio"); + method.setAccessible(true); + dbm = (int) method.invoke(signalStrength); + if (dbm<0) mSignalStrengths.putInt("wcdma_rscp",Dbm); + else mSignalStrengths.putInt("wcdma_rscp",Integer.MAX_VALUE); + mSignalStrengths.putInt("wcdma_ecio",dbm); + } catch (Exception ignored){} + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) + mSignalStrengths.putInt("level", signalStrength.getLevel()); + mEventFacade.postEvent("signal_strengths", mSignalStrengths.clone()); } }); } @@ -72,6 +96,22 @@ public class SignalStrengthFacade extends RpcReceiver { mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE); } + //新版安卓信号等级获取方式 + @Rpc(description = "Returns the Telephone Signal Strength Level .") + public int getTelephoneSignalStrengthLevel() throws Exception { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + return mTelephonyManager.getSignalStrength().getLevel(); + } else throw new Exception("getTelephoneSignalStrengthLevel only support Android >= 9.0"); + } + + //新版安卓信号强度获取方式 + @Rpc(description = "Returns the Telephone Signal Strength Detail .") + public String getTelephoneSignalStrengthDetail() throws Exception { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + return mTelephonyManager.getSignalStrength().toString(); + } else throw new Exception("getTelephoneSignalStrengthDetail only support Android >= 9.0"); + } + @Override public void shutdown() { stopTrackingSignalStrengths(); diff --git a/src/main/java/org/qpython/qsl4a/qsl4a/facade/USBHostSerialFacade.java b/src/main/java/org/qpython/qsl4a/qsl4a/facade/USBHostSerialFacade.java index b35ed9008e25e8d71b54029e29a11cd7a45f9d5c..dd35945a03a88bcb87b46ba071dc2ca51da6de7b 100644 --- a/src/main/java/org/qpython/qsl4a/qsl4a/facade/USBHostSerialFacade.java +++ b/src/main/java/org/qpython/qsl4a/qsl4a/facade/USBHostSerialFacade.java @@ -517,14 +517,14 @@ public class USBHostSerialFacade extends RpcReceiver { * connectionFailed: Indicate that the connection attempt failed and notify the UI Activity. {{{1 */ private void connectionFailed() { - mAndroidFacade.makeToast("USBHostSerial: Unable to connect device"); + mAndroidFacade.makeToast("USBHostSerial: Unable to connect device",0); } /** * connectionLost: Indicate that the connection was lost and notify the UI Activity. {{{1 */ private void connectionLost() { - mAndroidFacade.makeToast("USBHostSerial: connection lost"); + mAndroidFacade.makeToast("USBHostSerial: connection lost",0); } /** diff --git a/src/main/java/org/qpython/qsl4a/qsl4a/facade/VideoFacade.java b/src/main/java/org/qpython/qsl4a/qsl4a/facade/VideoFacade.java new file mode 100644 index 0000000000000000000000000000000000000000..3b724799e7684479aa4e754696b090f4bcdd2ed8 --- /dev/null +++ b/src/main/java/org/qpython/qsl4a/qsl4a/facade/VideoFacade.java @@ -0,0 +1,41 @@ +package org.qpython.qsl4a.qsl4a.facade; + +import android.app.Service; +import android.content.Intent; +import android.content.pm.PackageManager; + +import org.qpython.qsl4a.qsl4a.jsonrpc.RpcReceiver; +import org.qpython.qsl4a.qsl4a.rpc.Rpc; +import org.qpython.qsl4a.qsl4a.rpc.RpcDefault; +import org.qpython.qsl4a.qsl4a.rpc.RpcParameter; + +public class VideoFacade extends RpcReceiver { + + private final Service mService; + private final PackageManager mPackageManager; + private final AndroidFacade mAndroidFacade; + + public VideoFacade(FacadeManager manager) { + super(manager); + mService = manager.getService(); + mPackageManager = mService.getPackageManager(); + mAndroidFacade = manager.getReceiver(AndroidFacade.class); + } + + @Rpc(description = "Play the Video via Video Path .") + public void videoPlay( + @RpcParameter(name = "path") final String path, + @RpcParameter(name = "wait") @RpcDefault("true") Boolean wait) + throws Exception { + Intent intent = new Intent(); + intent.setClassName(mService.getPackageName(),"org.qpython.qpy.main.activity.VideoActivity"); + intent.putExtra("path", path); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.setAction(Intent.ACTION_VIEW); + mAndroidFacade.doStartActivity(intent,wait); + } + + @Override + public void shutdown() { + } +} diff --git a/src/main/java/org/qpython/qsl4a/qsl4a/jsonrpc/JsonRpcServer.java b/src/main/java/org/qpython/qsl4a/qsl4a/jsonrpc/JsonRpcServer.java index 8b41d800d70c6d790f39448f54a3a9d72872d3a1..959a4f2dad62d6abe8e724f4476c89f96e95d2a1 100644 --- a/src/main/java/org/qpython/qsl4a/qsl4a/jsonrpc/JsonRpcServer.java +++ b/src/main/java/org/qpython/qsl4a/qsl4a/jsonrpc/JsonRpcServer.java @@ -16,7 +16,7 @@ package org.qpython.qsl4a.qsl4a.jsonrpc; -import org.qpython.qsl4a.qsl4a.LogUtil; +//import org.qpython.qsl4a.qsl4a.LogUtil; import org.qpython.qsl4a.qsl4a.SimpleServer; import org.qpython.qsl4a.qsl4a.rpc.MethodDescriptor; import org.qpython.qsl4a.qsl4a.rpc.RpcError; @@ -32,7 +32,7 @@ import org.json.JSONObject; /** * A JSON RPC server that forwards RPC calls to a specified receiver object. - * + * * @author Damon Kohler (damonkohler@gmail.com) */ public class JsonRpcServer extends SimpleServer { @@ -42,7 +42,7 @@ public class JsonRpcServer extends SimpleServer { /** * Construct a {@link JsonRpcServer} connected to the provided {@link RpcReceiverManager}. - * + * * @param managerFactory * the {@link RpcReceiverManager} to register with the server * @param handshake @@ -66,28 +66,29 @@ public class JsonRpcServer extends SimpleServer { protected void handleConnection(Socket socket) throws Exception { RpcReceiverManager receiverManager = mRpcReceiverManagerFactory.create(); BufferedReader reader = - new BufferedReader(new InputStreamReader(socket.getInputStream()), 8192); + new BufferedReader(new InputStreamReader(socket.getInputStream()), 8192); PrintWriter writer = new PrintWriter(socket.getOutputStream(), true); - boolean passedAuthentication = false; + boolean unpass = true; String data; while ((data = reader.readLine()) != null) { - LogUtil.v("Received: " + data); + //LogUtil.v("Received: " + data); JSONObject request = new JSONObject(data); int id = request.getInt("id"); String method = request.getString("method"); JSONArray params = request.getJSONArray("params"); - // First RPC must be _authenticate if a handshake was specified. - if (!passedAuthentication && mHandshake != null) { - if (!checkHandshake(method, params)) { + // First RPC must be _authenticate //if a handshake was specified. + if (unpass) { + if (method.equals("_authenticate") && mHandshake.equals(params.getString(0))) { + unpass = false; + send(writer, JsonRpcResult.result(id, true)); + continue; + } else { SecurityException exception = new SecurityException("Authentication failed!"); send(writer, JsonRpcResult.error(id, exception)); shutdown(); throw exception; } - passedAuthentication = true; - send(writer, JsonRpcResult.result(id, true)); - continue; } MethodDescriptor rpc = receiverManager.getMethodDescriptor(method); @@ -98,22 +99,15 @@ public class JsonRpcServer extends SimpleServer { try { send(writer, JsonRpcResult.result(id, rpc.invoke(receiverManager, params))); } catch (Throwable t) { - LogUtil.e("Invocation error.", t); + //LogUtil.e("Invocation error.", t); send(writer, JsonRpcResult.error(id, t)); } } } - private boolean checkHandshake(String method, JSONArray params) throws JSONException { - if (!method.equals("_authenticate") || !mHandshake.equals(params.getString(0))) { - return false; - } - return true; - } - private void send(PrintWriter writer, JSONObject result) { writer.write(result + "\n"); writer.flush(); - LogUtil.v("Sent: " + result); + //LogUtil.v("Sent: " + result); } }