同一局域网内的两个apk通过socket互信通讯

前言:

最近客户提出了一个这样的需求,他们的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);
    }
}


                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值