package com.anyun.exam.lib; import android.Manifest; import android.app.Service; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.database.Cursor; import android.media.AudioManager; import android.media.MediaPlayer; import android.media.Ringtone; import android.media.RingtoneManager; import android.net.Uri; import android.os.Build; import android.os.Environment; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.os.Process; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.util.Base64; import android.util.Log; import com.anyun.exam.lib.net.Constant; import com.anyun.exam.lib.net.NtripTcpClient; import com.anyun.exam.lib.net.TcpSession; import com.anyun.exam.lib.util.Bluetooth; import com.anyun.exam.lib.util.BluetoothChatService; import com.anyun.exam.lib.util.BluetoothChatServiceCallback; import com.anyun.exam.lib.util.Constants; import com.anyun.exam.lib.util.DESUtil; import com.anyun.exam.lib.util.NetUtils; import com.anyun.exam.lib.util.ProperUtil; import com.anyun.exam.lib.util.Speaker; import com.anyun.exam.lib.util.SpeakerCallback; import androidx.annotation.Nullable; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Properties; import java.util.concurrent.atomic.AtomicBoolean; import java.util.regex.Pattern; import static android.content.pm.PackageManager.PERMISSION_GRANTED; /** * MyApplication2 * Created by lzw on 2019/6/5. 13:22:46 * 邮箱:632393724@qq.com * All Rights Saved! Chongqing AnYun Tech co. LTD */ public class RemoteService extends Service implements IRtcmData { private static final String TAG = "RemoteService"; public static final boolean mAyDevice = true; /**服务是否销毁标志*/ private AtomicBoolean mIsServiceDestroyed = new AtomicBoolean(false); private RemoteCallbackList mListenerList = new RemoteCallbackList(); private IListenerInterface mListener; private int msgId = 0; private Speaker speaker = null; private boolean ttsInitSucc = false; private int ringIndex = -1; private Uri ringUri = null; private Upgrade upgrade = null; private Bluetooth mBluetooth = null; private BluetoothChatService mChatService = null; private String mConnectedDeviceName = null; private String mConnectedDeviceAddr = null; private String mTargetBluetooth = null; private String mTargetBluetoothAddr = null; private boolean mDiscoveryBluetooth = false; public NtripTcpClient ntripTcpClient = null; private IRemoteInterface.Stub iRemoteInterface = new IRemoteInterface.Stub(){ @Override public void registListener(IListenerInterface i) throws RemoteException { //注册回调方法 mListenerList.register(i); } @Override public void unRegistListener(IListenerInterface i) throws RemoteException { mListenerList.unregister(i); } @Override public void add() throws RemoteException { Log.i(TAG,"客户端调用服务端方法"); } @Override public void SendCmd(int cmd, String value) throws RemoteException { if (cmd == 0x8100) { try { byte [] file = value.getBytes("ISO-8859-1"); // Log.d(TAG, byte2hex(file)); MainProcBinMsgEntry(cmd, file, file.length); } catch (UnsupportedEncodingException e) { Log.d(TAG, "UnsupportedEncodingException"); } } else { Log.d(TAG, "Process " + Process.myPid() + " Thread " + Thread.currentThread().getId() + " RecvMsgFromMainProc cmd = " + String.format(" %04X ", cmd) + " length " + value.length()); MainProcMsgEntry(cmd, value.trim()); } } }; @Nullable @Override public IBinder onBind(Intent intent) { return iRemoteInterface; } @Override public void onCreate() { super.onCreate(); Log.i(TAG,"onCreate()"); speaker = new Speaker(/*getApplicationContext()*/this, new TTSCallback()); new Thread(new StartNative()).start(); new Thread(new TestThread()).start(); // new Thread(new AutoUpdateMcuThread(this)).start(); upgrade = Upgrade.getInstance(getApplicationContext()); ringUri = GetRingIndex(this, "Antimony"); // PlayRing(this, ringUri); LimitMaxMinVolume(); if (mAyDevice == false) { mBluetooth = Bluetooth.getInstance(getApplicationContext(), mHandler); mBluetooth.OpenBluetooth(); // Initialize the BluetoothChatService to perform mBluetooth connections mChatService = new BluetoothChatService(this, mHandler); } Log.d(TAG, "基带版本 " + getBaseband_Ver()); String ver = getBaseband_Ver(); new Thread(new TestCls()).start(); Rtcm.INSTANCE.registerCallback(this); TcpSession tcpSession = new TcpSession(); tcpSession.ip = "base.staroadnav.com"; // tcpSession.ip = "192.168.16.212"; tcpSession.phone = ""; tcpSession.setPort(6060); // tcpSession.setPort(8080); ntripTcpClient = new NtripTcpClient(tcpSession); ntripTcpClient.connect(this); } class TestCls implements Runnable { @Override public void run() { try { Thread.sleep(5000); } catch (InterruptedException e) { } upgrade.ManualUpgrade(Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "/Download/aks3b.apk"); } } class AutoUpdateMcuThread implements Runnable { private Context context; public AutoUpdateMcuThread(Context context) { this.context = context; } @Override public void run() { Properties proper = ProperUtil.getProperties(getApplicationContext()); if (proper != null) { String assetVer = proper.getProperty("mcuVersion"); if (assetVer != null) { try { InputStream inputStream = context.getAssets().open("dfu.bin"); if (inputStream != null) { int fileLength = inputStream.available(); Log.d(TAG, "AutoUpdateMcu " + fileLength); if (fileLength > 0) { byte[] temp = new byte[fileLength]; inputStream.read(temp); UpgradeMcu(assetVer, temp); } inputStream.close(); } } catch (IOException e) { } } } } } private void LimitMaxMinVolume() { AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); if (audioManager != null) { int currentVolume = audioManager.getStreamVolume(AudioManager.STREAM_RING); int maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_RING); Log.d(TAG, String.format("Ring音量 = %d Max = %d", currentVolume, maxVolume)); if (currentVolume < maxVolume - 1) { Log.d(TAG, "调至默认Ring音量"); audioManager.setStreamVolume(AudioManager.STREAM_RING, maxVolume - 1, 0); } } } public String getBaseband_Ver(){ String Version = ""; try { Class cl = Class.forName("android.os.SystemProperties"); Object invoker = cl.newInstance(); Method m = cl.getMethod("get", new Class[] { String.class,String.class }); Object result = m.invoke(invoker, new Object[]{"gsm.version.baseband", "no message"}); Version = (String)result; } catch (Exception e) { } return Version; } private Uri GetRingIndex(Context context, String ring) { RingtoneManager ringtoneManager= new RingtoneManager(context); // 铃声管理器 ringtoneManager.setType(RingtoneManager.TYPE_NOTIFICATION); for (int i = 0; i < ringtoneManager.getCursor().getCount(); i++) { if (ringtoneManager.getRingtone(i).getTitle(context).equals(ring)) { Log.d(TAG, "得到铃声 " + i); return ringtoneManager.getRingtoneUri(i); } } return null; } public void PlayRing(Context context, Uri src) { if (src == null) return; final MediaPlayer mediaPlayer = new MediaPlayer(); try { mediaPlayer.setDataSource(context, src); mediaPlayer.setAudioStreamType(AudioManager.STREAM_NOTIFICATION); mediaPlayer.setLooping(false); mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { // 在播放完毕被回调 Log.d(TAG, "播放完成"); mediaPlayer.stop(); mediaPlayer.release(); } }); mediaPlayer.prepareAsync(); mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { // 装载完毕回调 Log.d(TAG, "装载完毕回调"); mediaPlayer.start(); } }); } catch (Exception e) { Log.e(TAG, e.getMessage()); } } class TestThread implements Runnable { @Override public void run() { try { Thread.sleep(30000); // Ota ota = new Ota(); // ota.excuteUpdateZip(getApplicationContext(), ""); } catch (InterruptedException e) { } } } class StartNative implements Runnable { @Override public void run() { startNative(mAyDevice); } } @Override public void onDestroy() { super.onDestroy(); Log.i(TAG,"onDestroy"); Rtcm.INSTANCE.unRegisterCallback(); if (mChatService != null) { mChatService.stop(); } if (mBluetooth != null) { mBluetooth.CloseBluetooth(); mBluetooth.unRegisterReceiver(); } mIsServiceDestroyed.set(true); Log.d(TAG, "onDestory executed 进程 " + Process.myPid()); Process.killProcess(Process.myPid()); } private int onMessageArrived(int cmd, String json) { Log.d(TAG, "SendMsgToMainProc cmd = " + String.format("%04X", cmd) + " json = " + json); int N = mListenerList.getRegisteredCallbackCount(); int ret = -1; synchronized(this) { mListenerList.beginBroadcast(); for (int i = 0; i < N; i++) { mListener = mListenerList.getBroadcastItem(i); if (mListener != null) { try { mListener.onMessageArrived(cmd, json); ret = 0; } catch (RemoteException e) { e.printStackTrace(); } }else{ } } mListenerList.finishBroadcast(); } return ret; } public int SendMsgToMainProc(int cmd, String value) { if (!mIsServiceDestroyed.get()){ return onMessageArrived(cmd, value); } return -2; } public String javaDESEncrypt(String plaintext, String key) { try { byte []des = DESUtil.encrypt(plaintext.getBytes("utf-8"), key); return Base64.encodeToString(des, Base64.DEFAULT); } catch (Exception e) { } return null; } public byte[] javaDESEncrypt(byte []plaintext, byte []key) { try { return DESUtil.encrypt(plaintext, key); } catch (Exception e) { } return null; } public void PlayBreakRing() { if (ringUri != null) { PlayRing(this, ringUri); } } public void TextSpeak(String text, int id) { if (speaker != null && ttsInitSucc) { speaker.speak(text, Integer.toString(id)); } else { TextSpeakEnd(id); } } public void TextSpeakInitCallback(boolean ret) { ttsInitSucc = ret; } private String byte2hex(byte [] buffer){ StringBuilder h = new StringBuilder(); Log.d(TAG, "byte buffer length = " + buffer.length); for(int i = 0; i < buffer.length; i++){ String temp = Integer.toHexString(buffer[i] & 0xFF); if(temp.length() == 1){ temp = "0" + temp; } h.append(temp); h.append(" "); } return h.toString(); } class TTSCallback implements SpeakerCallback { @Override public void PlayInit(boolean ret) { Log.d(TAG, "TTS引擎初始化成功"); ttsInitSucc = ret; } @Override public void PlayStart(String s) { Log.d(TAG, "TTS引擎播放开始"); } @Override public void PlayDone(String s) { Log.d(TAG, "TTS引擎播放结束"); TextSpeakEnd(Integer.valueOf(s)); } @Override public void PlayError(String s) { Log.d(TAG, "TTS引擎播放出错"); TextSpeakEnd(Integer.valueOf(s)); } } public void GetUpgrade(int province, int city) { if (upgrade != null) { upgrade.CheckUpgrade(province, city); } } public void ConnectBluetooth(String name, String pin) { if (mBluetooth != null && mChatService != null) { Log.d(TAG, "执行蓝牙连接请求 " + name); mBluetooth.SetPin(pin); mTargetBluetooth = name; if (isMac(name)) { mTargetBluetoothAddr = name; handlerConnectBluetooth.removeCallbacks(runnableConnectBluetooth); handlerConnectBluetooth.postDelayed(runnableConnectBluetooth, 500); } else { mDiscoveryBluetooth = true; mBluetooth.doDiscovery(name); } } else { Log.d(TAG, "拒绝蓝牙连接请求 " + name); } } public void DisconnectBluetooth() { handlerConnectBluetooth.removeCallbacks(runnableConnectBluetooth); if (mChatService != null) { mChatService.stop(); } } Handler handlerConnectBluetooth = new Handler(); Runnable runnableConnectBluetooth = new Runnable() { @Override public void run() { if (mChatService != null && mTargetBluetoothAddr != null) { mChatService.connect(mTargetBluetoothAddr, true); } } }; public boolean isMac(String addr) { String pattern = "^([0-9A-Fa-f]{2})(:[0-9A-Fa-f]{2}){5}$"; return Pattern.matches(pattern, addr); } public void WriteBluetooth(byte []data) { if (mChatService != null && mChatService.getState() == BluetoothChatService.STATE_CONNECTED) { mChatService.write(data); } } private final Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case Constants.MESSAGE_BLUETOOTH_STATUS: if (msg.arg1 == 1) { Log.d(TAG, "蓝牙开启"); // mBluetooth.doDiscovery(); if (mChatService != null) { // mChatService.connect("00:1D:43:9A:E0:79", true); // mChatService.connect("00:1A:7D:DA:71:11", true); } BluetoothStatusChange(1); } else { Log.d(TAG, "蓝牙关闭"); BluetoothStatusChange(0); } break; case Constants.MESSAGE_BLUETOOTH_FOUND: String btaddr = msg.getData().getString(Constants.DEVICE_ADDRESS); Log.d(TAG, "发现设备 " + btaddr); if (mDiscoveryBluetooth) { mTargetBluetoothAddr = btaddr; } break; case Constants.MESSAGE_BLUETOOTH_DISCOVERY_FINISHED: Log.d(TAG, "搜索结束"); if (mDiscoveryBluetooth) { handlerConnectBluetooth.removeCallbacks(runnableConnectBluetooth); handlerConnectBluetooth.postDelayed(runnableConnectBluetooth, 500); } mDiscoveryBluetooth = false; break; case Constants.MESSAGE_STATE_CHANGE: switch (msg.arg1) { case BluetoothChatService.STATE_CONNECTED: Log.d(TAG, "蓝牙已连接"); // BluetoothStatusChange(3); BluetoothConnected(mConnectedDeviceName, mConnectedDeviceAddr); break; case BluetoothChatService.STATE_CONNECTING: Log.d(TAG, "蓝牙连接中..."); break; case BluetoothChatService.STATE_LISTEN: Log.d(TAG, "蓝牙监听"); BluetoothStatusChange(2); break; case BluetoothChatService.STATE_NONE: Log.d(TAG, "蓝牙无效"); BluetoothStatusChange(2); handlerConnectBluetooth.removeCallbacks(runnableConnectBluetooth); handlerConnectBluetooth.postDelayed(runnableConnectBluetooth, 5000); break; } break; case Constants.MESSAGE_WRITE: break; case Constants.MESSAGE_READ: // Log.d(TAG, String.format("蓝牙数据 length = %d 线程 %d", msg.arg1, Thread.currentThread().getId())); BluetoothDataComeIn((byte[]) msg.obj, msg.arg1); /*if (ndkUtils != null) { byte[] readBuf = (byte[]) msg.obj; ndkUtils.bluetoothMoreData(readBuf, msg.arg1); }*/ break; case Constants.MESSAGE_DEVICE_NAME: // save the connected device's name mConnectedDeviceName = msg.getData().getString(Constants.DEVICE_NAME); Log.d(TAG, "MESSAGE_DEVICE_NAME: " + mConnectedDeviceName); break; case Constants.MESSAGE_DEVICE_ADDRESS: mConnectedDeviceAddr = msg.getData().getString(Constants.DEVICE_ADDRESS); Log.d(TAG, "MESSAGE_DEVICE_ADDRESS: " + mConnectedDeviceAddr); break; case Constants.MESSAGE_TOAST: break; default:break; } } }; class DataCallback implements BluetoothChatServiceCallback { @Override public void iDataComeIn(byte []data, int length) { } } @Override public void sendRtcm(byte []data, int length) { uploadRtcm(data, length); } // Used to load the 'native-lib' library on application startup. static { System.loadLibrary("native-lib"); } public native void startNative(boolean ayDevice); public native void MainProcMsgEntry(int cmd, String value); public native void MainProcBinMsgEntry(int cmd, byte []data, int length); public native void UpgradeMcu(String vercode, byte []rom); public native void TextSpeakEnd(int id); public native void BluetoothConnected(String name, String addr); public native void BluetoothStatusChange(int status); public native void BluetoothDataComeIn(byte []data, int length); public native void uploadRtcm(byte []data, int length); }