前言:
最近客户提出了一个这样的需求,他们的apk想要获取到我们rk3188板的参数和一些控制板卡的命令如(音量+、音量-、关机、重启、亮度+、亮度-)等等。但是又不想让他们的apk直接和板卡有任务关系,所以就采用到了这样的办法,采用sokcet局域网通信机制。把客户的apk作为socket服务端,然后再写一个apk作为socket客户端,装在同一台机器上面,这样就可以实现客户的需求了。
步骤一:创建一个ClientServer Demo 并 编写客户端代码
代码里面都有详细注释,写在服务里面的。
由于博主是用的以太网所以HOST地址填写的:127.0.0.1 PORT地址随便填写的。
如果你们用的wifi或者手机共享网络,HOST地址就填写相应的址
MainSocketClientService.java
package com.android.clientserver; import android.app.Service; import android.content.Intent; import android.media.AudioManager; import android.os.IBinder; import android.support.annotation.Nullable; import android.util.Log; import org.json.JSONException; import org.json.JSONObject; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.ref.WeakReference; import java.net.Socket; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Date; import java.util.Timer; import java.util.TimerTask; /** * Created by Administrator on 2018/5/19. */ public class MainSocketClientService extends Service { private static final String TAG = "MainSocketClientService"; private static final String HOST = "127.0.0.1"; private static final int PORT = 12345; private WeakReference<Socket> mSocket; private ReadThread mReadThread; private static SocketThread socketThread = null; private AudioManager mAudioManager; private double maxVolume; private synchronized SocketThread instance() { if (socketThread == null) { socketThread = new SocketThread(); } return socketThread; } private synchronized void destroyInstance() { if (socketThread != null) { socketThread = null; } } @Override public void onCreate() { super.onCreate(); Log.d(TAG, "MainSocketClientService onCreate......"); mAudioManager = (AudioManager) getSystemService(AUDIO_SERVICE); maxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); instance().start(); } public class SocketThread extends Thread { @Override public void run() { super.run(); initSocket(); } } /** * 初始化SocketReadThread */ private void initSocket() { try { Socket socket = new Socket(HOST, PORT); socket.setOOBInline(true); mSocket = new WeakReference<Socket>(socket); mReadThread = new ReadThread(socket); mReadThread.start(); // 每隔十秒发送一个心跳给服务端,判断socket连接是否ok new Timer().schedule(new TimerTask() { @Override public void run() { String heartBeat = "{\"cmd\":\"heartbeat\"}" + "#end#" + "\t\t" + new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date().getTime()); boolean isSuccess = sendMsg(heartBeat); Log.d(TAG, "MainSocketClientService isSuccess = " + isSuccess); // 如果isSuccess返回false,就说明socket连接掉线,然后重连 if (!isSuccess) { Log.d(TAG, "MainSocketClientService socket断开连接,重连socket......"); mReadThread.release(); new Thread(new Runnable() { @Override public void run() { initSocket(); } }).start(); } } }, 0, 5000); } catch (IOException e) { e.printStackTrace(); Log.d(TAG, "MainSocketClientService initSocket IOException e = " + e.getMessage()); try { Thread.sleep(5000); initSocket(); } catch (InterruptedException e1) { e1.printStackTrace(); } } } /** * 接收来自服务器的数据 */ class ReadThread extends Thread { private WeakReference<Socket> mWeakSocket; private boolean isStart = true; public ReadThread(Socket socket) { mWeakSocket = new WeakReference<Socket>(socket); } public void release() { isStart = false; if (mWeakSocket != null) { releaseLastSocket(mWeakSocket); } } @Override public void run() { super.run(); Socket socket = mWeakSocket.get(); if (null != socket) { try { InputStream is = socket.getInputStream(); byte[] buffer = new byte[1024 * 4]; int length = 0; while (!socket.isClosed() && !socket.isInputShutdown() && isStart && ((length = is.read(buffer)) != -1)) { Log.d(TAG, "MainSocketClientService ReadThread socket = " + socket + "\r\n" + "length = " + length); if (length > 0) { String getServerMessage = new String(Arrays.copyOf(buffer, length)).trim(); Log.d(TAG, "MainSocketClientService ReadThread getServerMessage = " + getServerMessage); JSONObject jsonObject = new JSONObject(getServerMessage); String cmd = jsonObject.getJSONObject("data").getString("cmd"); switch (cmd) { case "increaseVoice":// 音量+ 100 Log.d(TAG, "MainSocketClientService increaseVoice......"); double increaseVolume = jsonObject.getJSONObject("data").getInt("increaseVolume"); mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, (int) Math.floor(maxVolume * (increaseVolume / 100)), 0); break; case "reduceVoice":// 音量- 0 Log.d(TAG, "MainSocketClientService reduceVoice......"); double reduceVolume = jsonObject.getJSONObject("data").getInt("reduceVolume"); mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, (int) Math.floor(maxVolume * (reduceVolume / 100)), 0); break; case "shutdown":// 关机 Log.d(TAG, "MainSocketClientService shutdown......"); int shutdownTime = jsonObject.getJSONObject("data").getInt("shutdownTime"); String[] arrayShutDown = {"su", "-c", "reboot -p"}; try { Thread.sleep(shutdownTime * 1000); Runtime.getRuntime().exec(arrayShutDown); } catch (IOException e) { e.printStackTrace(); Log.d(TAG, "MainSocketClientService shutdown IOException e = " + e.getMessage()); } catch (InterruptedException e) { e.printStackTrace(); } break; case "reboot":// 重启机器 Log.d(TAG, "MainSocketClientService reboot......"); int rebootTime = jsonObject.getJSONObject("data").getInt("rebootTime"); String[] arrayReboot = {"su", "-c", "reboot"}; try { Thread.sleep(rebootTime * 1000); Runtime.getRuntime().exec(arrayReboot); } catch (IOException e) { e.printStackTrace(); Log.d(TAG, "MainSocketClientService reboot IOException e = " + e.getMessage()); } catch (InterruptedException e) { e.printStackTrace(); } break; case "increaseBrightness":// 亮度+ 100 Log.d(TAG, "MainSocketClientService increaseBrightness......"); double addBrightnessValue = jsonObject.getJSONObject("data").getInt("addBrightnessValue"); break; case "reduceBrightness":// 亮度- 0 Log.d(TAG, "MainSocketClientService reduceBrightness......"); double reduceBrightnessValue = jsonObject.getJSONObject("data").getInt("reduceBrightnessValue"); break; case "machineParameters":// 获取到板卡参数发送到服务端app Log.d(TAG, "MainSocketClientService machineParameters......"); String wifiMacAddress = DeviceUtils.getWlanMac(); String versionName = DeviceUtils.getVersionName(MainSocketClientService.this); int versionCode = DeviceUtils.getVersionCode(MainSocketClientService.this); String appName = DeviceUtils.getAppName(MainSocketClientService.this); JSONObject jsonObject1 = new JSONObject(); jsonObject1.put("wifiMacAddress", wifiMacAddress); jsonObject1.put("versionName", versionName); jsonObject1.put("versionCode", versionCode); jsonObject1.put("appName", appName); String machineParametersJsonData = jsonObject1.toString() + "#end#"; Log.d(TAG, "MainSocketClientService machineParametersJsonData = " + machineParametersJsonData); sendMsg(machineParametersJsonData); break; } } } } catch (IOException e) { e.printStackTrace(); Log.d(TAG, "MainSocketClientService ReadThread IOException e = " + e.getMessage()); } catch (JSONException e) { e.printStackTrace(); Log.d(TAG, "MainSocketClientService ReadThread JSONException e = " + e.getMessage()); } } } } /** * 从客户端app通过socket传输数据到服务端app * * @param msg * @return */ private boolean sendMsg(final String msg) { if (null == mSocket || null == mSocket.get()) { Log.d(TAG, "MainSocketClientService mSocket为空或者mSocket.get()为空......"); return false; } final Socket soc = mSocket.get(); if (!soc.isClosed() && !soc.isOutputShutdown()) { new Thread(new Runnable() { @Override public void run() { try { OutputStream os = soc.getOutputStream(); String sendMessage = msg + "\r\n"; if (sendMessage != null && !"".equals(sendMessage)) { os.write(sendMessage.getBytes()); os.flush(); } } catch (IOException e) { e.printStackTrace(); Log.d(TAG, "MainSocketClientService sendMsg IOException e = " + e.getMessage()); } } }).start(); } else { Log.d(TAG, "MainSocketClientService soc.isClosed并且soc.isOutputShutdown()......"); return false; } return true; } private void releaseLastSocket(WeakReference<Socket> mSocket) { // try{ // if(null != mSocket){ // Socket sk = mSocket.get(); // if(sk == null){ // return; // } // if(!sk.isClosed()){ // sk.close(); // } // sk = null; // mSocket = null; // } // }catch (IOException e){ // e.printStackTrace(); // Log.d(TAG,"MainSocketClientService releaseLastSocket e= " + e.getMessage() ); // } try { if (mSocket != null) { Socket sk = mSocket.get(); sk.close(); } } catch (IOException e) { e.printStackTrace(); Log.d(TAG, "MainSocketClientService releaseLastSocket e= " + e.getMessage()); } } @Nullable @Override public IBinder onBind(Intent intent) { return null; } @Override public void onDestroy() { super.onDestroy(); if (mReadThread != null) { mReadThread.release(); } if (mSocket != null) { releaseLastSocket(mSocket); } destroyInstance(); } }
这个是获取设备信息的工具类,只是作测试用的
package com.android.clientserver; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.util.Log; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; /** * Created by Administrator on 2018/5/19. */ public class DeviceUtils { private static final String TAG = "DeviceUtils"; public static String getWlanMac() { try { Log.d(TAG, "getWlanMac:" + loadFileAsString("/sys/class/net/wlan0/address").toUpperCase().substring(0, 17)); return loadFileAsString("/sys/class/net/wlan0/address").toUpperCase().substring(0, 17); } catch (Exception e) { Log.e(TAG, "open sys/class/net/eth0/address failed : " + e); return ""; } } private static String loadFileAsString(String filePath) throws IOException { StringBuffer sb = new StringBuffer(1000); BufferedReader br = new BufferedReader(new FileReader(filePath)); char[] buf = new char[1024]; int numRead = 0; while ((numRead = br.read(buf)) != -1) { String readData = String.valueOf(buf, 0, numRead); sb.append(readData); } br.close(); return sb.toString(); } /** * 获取版本名称 * * @param context 上下文 * @return 版本名称 */ public static String getVersionName(Context context) { // 获取包管理器 PackageManager pm = context.getPackageManager(); // 获取包信息 try { PackageInfo packageInfo = pm.getPackageInfo(context.getPackageName(), 0); // 返回版本名称 return packageInfo.versionName; } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } return null; } /** * 获取版本号 * * @param context 上下文 * @return 版本号 */ public static int getVersionCode(Context context) { // 获取包管理器 PackageManager pm = context.getPackageManager(); // 获取包信息 try { PackageInfo packageInfo = pm.getPackageInfo(context.getPackageName(), 0); // 返回版本号 return packageInfo.versionCode; } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } return 0; } /** * 获取App的名称 * * @param context 上下文 * @return App名称 */ public static String getAppName(Context context) { // 获取包管理器 PackageManager pm = context.getPackageManager(); // 获取包信息 try { PackageInfo packageInfo = pm.getPackageInfo(context.getPackageName(), 0); // 获取应用信息 ApplicationInfo applicationInfo = packageInfo.applicationInfo; //获取labelRes int labelRes = applicationInfo.labelRes; // 返回App的名称 return context.getResources().getString(labelRes); } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } return null; } }
步骤二:创建一个SocketServer Demo 并 编写服务端代码
MainSocketServer.java
package com.android.socketserver; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Button; import android.widget.TextView; /** * Created by Administrator on 2018/5/19. */ public class MainSocketServer extends AppCompatActivity implements View.OnClickListener { private static final String TAG = "MainSocketServer"; String abc = "{ \"data\": {\"cmd\": \"reboot\", \"time\": 3}}"; private Button increase_voice_btn; private Button reduce_voice_btn; private Button shutdown_btn; private Button reboot_btn; private Button increase_brightness_btn; private Button reduce_brightness_btn; private Button display_machine_parameters_btn; private TextView display_machine_parameters_tv; //启动服务端端口服务端IP private SocketServer server = new SocketServer(12345); private StringBuilder stringBuilder; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); stringBuilder = new StringBuilder(); // socket服务端开始监听 server.beginListen(); // socket收到消息线程 SocketServer.serverHandler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); stringBuilder.append(msg.obj.toString()); stringBuilder.append("\r\n"); display_machine_parameters_tv.setText(stringBuilder); } }; } private void initView() { increase_voice_btn = (Button) findViewById(R.id.increase_voice_btn); reduce_voice_btn = (Button) findViewById(R.id.reduce_voice_btn); shutdown_btn = (Button) findViewById(R.id.shutdown_btn); reboot_btn = (Button) findViewById(R.id.reboot_btn); increase_brightness_btn = (Button) findViewById(R.id.increase_brightness_btn); reduce_brightness_btn = (Button) findViewById(R.id.reduce_brightness_btn); display_machine_parameters_btn = (Button) findViewById(R.id.display_machine_parameters_btn); display_machine_parameters_tv = (TextView) findViewById(R.id.display_machine_parameters_tv); initListener(); } private void initListener() { increase_voice_btn.setOnClickListener(this); reduce_voice_btn.setOnClickListener(this); shutdown_btn.setOnClickListener(this); reboot_btn.setOnClickListener(this); increase_brightness_btn.setOnClickListener(this); reduce_brightness_btn.setOnClickListener(this); display_machine_parameters_btn.setOnClickListener(this); } @Override public void onClick(View view) { switch (view.getId()) { case R.id.increase_voice_btn: // 发送指令,把音量调成100 String increaseVoice = "{ \"data\": { \"cmd\": \"increaseVoice\", \"increaseVolume\":100}}" + "#end#"; server.sendMessage(increaseVoice); break; case R.id.reduce_voice_btn: // 发送指令,把音量调成0 String reduceVoice = "{ \"data\": { \"cmd\": \"reduceVoice\", \"reduceVolume\":0}}" + "#end#"; server.sendMessage(reduceVoice); break; case R.id.shutdown_btn: // 发送指令 3秒后关闭机器 String shutdown = "{ \"data\": { \"cmd\": \"shutdown\", \"shutdownTime\":3}}" + "#end#"; server.sendMessage(shutdown); break; case R.id.reboot_btn: // 发送指令 3秒后重启机器 String reboot = "{ \"data\": { \"cmd\": \"reboot\", \"rebootTime\":3}}" + "#end#"; server.sendMessage(reboot); break; case R.id.increase_brightness_btn: // 发送指令,把亮度调成100 String increaseBrightness = "{ \"data\": { \"cmd\": \"increaseBrightness\", \"addBrightnessValue\":100}}" + "#end#"; server.sendMessage(increaseBrightness); break; case R.id.reduce_brightness_btn: // 发送指令,把亮度调成100 String reduceBrightness = "{ \"data\": { \"cmd\": \"reduceBrightness\", \"reduceBrightnessValue\":0}}" + "#end#"; server.sendMessage(reduceBrightness); break; case R.id.display_machine_parameters_btn: // 发送指令 获取板卡参数 String machineParameters = "{ \"data\": { \"cmd\": \"machineParameters\"}}" + "#end#"; server.sendMessage(machineParameters); break; } } }
SocketServer封装类
package com.android.socketserver; import android.os.Handler; import android.os.Message; import android.util.Log; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.util.Arrays; /** * Created by Administrator on 2018/5/19. */ public class SocketServer { private static final String TAG = "SocketServer"; private ServerSocket server; private Socket mSocket; private InputStream in; private String getClientData = ""; private boolean isClient = false; public static Handler serverHandler; /** * 初始化服务端 * * @param port */ public SocketServer(int port) { try { server = new ServerSocket(port); isClient = true; } catch (IOException e) { e.printStackTrace(); Log.d(TAG, "SocketServer IOException e = " + e.getMessage()); } } /** * socket监听数据 */ public void beginListen() { new Thread(new Runnable() { @Override public void run() { try { Log.d(TAG, "SocketServer beginListen......"); // 接受请求 if (server != null && isClient == true) { mSocket = server.accept(); } // 得到输入流 in = mSocket.getInputStream(); // 实现数据循环接收 while (mSocket.isConnected()) { byte[] buffer = new byte[1024 * 4]; int length = in.read(buffer); getClientData = new String(Arrays.copyOf(buffer, length)).trim(); Log.d(TAG, "SocketServer beginListen getClientData = " + getClientData); if (getClientData != null && !"".equals(getClientData) && getClientData != "exit") { returnMessage(getClientData); } else if (getClientData == null || getClientData == "exit") { break; } } } catch (IOException e) { Log.d(TAG, "SocketServer beginListen IOException e = " + e.getMessage()); mSocket.isClosed(); } } }).start(); } /** * socket服务端发送指令给客户端 * * @param toClientCommand */ public void sendMessage(final String toClientCommand) { Thread thread = new Thread(new Runnable() { @Override public void run() { try { if (mSocket != null && !mSocket.isClosed() && toClientCommand != null) { Log.d(TAG, "SocketServer sendMessage toClientCommand = " + toClientCommand); PrintWriter out = new PrintWriter(mSocket.getOutputStream()); out.print(toClientCommand); out.flush(); } } catch (IOException e) { e.printStackTrace(); Log.d(TAG, "SocketServer sendMessage IOException e = " + e.getMessage()); } } }); thread.start(); } /** * socket服务端得到返回的数据并发送到主界面 * * @param getClientData */ public void returnMessage(String getClientData) { Message msg = new Message(); msg.obj = getClientData; serverHandler.sendMessage(msg); } }