Android 手机和盒子遥控器

需求

最近在公司中没有明确要做的东西,开会的时候说可能会做手机端的遥控器PS:我现在做的是电视盒子,然后就从网上看了一下,几个遥控器软件中就看悟空遥控器比较好用一点,也比较能让人接受,所以就准备写一个Demo 实现一下这个遥控器。

实现

当然就是这种操作肯定是需要一种连接,但是呢,假如说我们建立一个长连接(建立在网络端)的,这种肯定不符合我们的需求了,我们TV的操作需求其实只能是在眼睛可视范围之内进行操作,不满足这条件,我们的操作将会失去意义,所以我选择的是Socket 的连接,完成客户端按键命令的发送,

一、先看一下 Demo的界面

这里写图片描述

好吧 不知道为什么最近为什么图大小不能改变 现在就不管了

二、客户端

就是上面的图片中的功能,我们的设想是更具UI界面中的组件去操作TV的按键功能,看一下代码

class MainActivity : Activity(), View.OnClickListener {
    private lateinit var mSocket: Socket
    private lateinit var button_tv: Button
    private var isConnection: Boolean = false
    private var ip: String = "192.168.1.95"
    private val PORT: Int = 54321


    override fun onClick(p0: View?) {
        when (p0?.id) {
            R.id.button_left -> sendOrderCode(KeyEvent.KEYCODE_DPAD_LEFT)
            R.id.button_up -> sendOrderCode(KeyEvent.KEYCODE_DPAD_UP)
            R.id.button_right -> sendOrderCode(KeyEvent.KEYCODE_DPAD_RIGHT)
            R.id.button_down -> sendOrderCode(KeyEvent.KEYCODE_DPAD_DOWN)
            R.id.button_ok -> sendOrderCode(KeyEvent.KEYCODE_ENTER)
            R.id.button_back -> sendOrderCode(KeyEvent.KEYCODE_BACK)
            R.id.button_home -> sendOrderCode(KeyEvent.KEYCODE_HOME)
            R.id.button_add -> sendOrderCode(KeyEvent.KEYCODE_VOLUME_UP)
            R.id.button_minus -> sendOrderCode(KeyEvent.KEYCODE_VOLUME_DOWN)
        }
    }

    private fun sendOrderCode(code: Int) {
        Thread(Runnable {
            var socket: Socket? = null
            try {
                socket = Socket("IP 地址", 6868)
            } catch (e: IOException) {
                e.printStackTrace()
            }
            var os: OutputStream? = null
            try {
                os = socket!!.getOutputStream()
            } catch (e: IOException) {
                e.printStackTrace()
            }

            val ps = PrintStream(os!!)
            ps.println(code)
            ps.flush()
            ps.close()
            try {
                os.close()
            } catch (e: IOException) {
                e.printStackTrace()
            }

            try {
                socket!!.close()
            } catch (e: IOException) {
                e.printStackTrace()
            }
        }).start()

    }


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        button_tv = findViewById(R.id.button_connection_tv)
        initClick()
    }

    private fun initClick() {
        findViewById<Button>(R.id.button_left).setOnClickListener(this)
        findViewById<Button>(R.id.button_up).setOnClickListener(this)
        findViewById<Button>(R.id.button_right).setOnClickListener(this)
        findViewById<Button>(R.id.button_down).setOnClickListener(this)
        findViewById<Button>(R.id.button_ok).setOnClickListener(this)
        findViewById<Button>(R.id.button_back).setOnClickListener(this)
        findViewById<Button>(R.id.button_home).setOnClickListener(this)
        findViewById<Button>(R.id.button_add).setOnClickListener(this)
        findViewById<Button>(R.id.button_minus).setOnClickListener(this)
        button_tv.setOnClickListener({
            object : Thread() {
                override fun run() {
                    val connectionTV = connectionTV()
                    if (connectionTV) {
                        Log.e("状态", "连接状态" + "成功")
                        isConnection = true
                    }
                }
            }

        })
    }

    private fun connectionTV(): Boolean {
        mSocket = Socket(ip, PORT)
        while (true) {
            val inputStream = DataInputStream(mSocket.getInputStream())
            val s = inputStream.readUTF()
            if (!TextUtils.isEmpty(s)) {
                if ("ok" == s) {
                    return true
                }
            }
            return false
        }

    }


}

我们通过Socket实现连接 ,发送按键指令
上述代码中出现的KeyEvent 的按键的值均为Demo图对应的值,其他址可以看 KeyEvent 的键值

三 、 服务端

服务端,就是TV 上的Demo ,TV上的项目当然我们使用的就是服务去操作按键指令了,先看一下代码

public class TVService extends Service {
    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (msg.what == 0) {
                int keyCode = msg.arg1;
                onKeyEvent(keyCode);
            }
        }
    };

    public static void onKeyEvent(final int keyCode) {
        new Thread() {
            public void run() {
                try {
                    Instrumentation inst = new Instrumentation();
                    inst.sendKeyDownUpSync(keyCode);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }.start();
    }

    public TVService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public void onCreate() {
        super.onCreate();

    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        startSocketServer();
        return super.onStartCommand(intent, flags, startId);
    }

    private void startSocketServer() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                ServerSocket server;
                try {
                    server = new ServerSocket(6868);
                    System.out.println("Tvsr:Server Started!");
                    while (true) {
                        System.out.println("Tvsr:Server Runing!");
                        Socket client = server.accept();
                        InputStream ins = client.getInputStream();
                        BufferedReader br = new BufferedReader(new InputStreamReader(ins));
                        final String tmp = br.readLine();
                        final int keyCode = Integer.parseInt(tmp);
                        new Thread(new Runnable() {
                            @Override
                            public void run() {
                                Message message = Message.obtain();
                                message.what = 0;
                                message.arg1 = keyCode;
                                mHandler.sendMessage(message);
                            }
                        }).start();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
        }).start();

    }
}

上述的代码就是服务端的代码,使用的是Instrumentation 做事件注入 ,运行的时候你会发现需要添加一个权限

    <uses-permission android:name="android.permission.INJECT_EVENTS"/>

这是一个系统权限 ,你的操作要是在Activity中,是不需要这个权限的,但是服务中去操作其它应用程序时需要这个权限,添加这个权限之后会报错,当然,这时我们需要将我们的应用签名成系统应用签名的文件,并且在AndroidManifest.xml 的manifest节点上添加android:sharedUserId=”android.uid.system”该属性,
当然很操蛋的是如何将应用打包成系统签名文件的应用,我很幸运我们的盒子的签名文件是一样的,并且是提供给我的,这就加速了我的Demo的完成,要是你没有系统签名,那就去寻找,要是找不到,那你就蛋碎了(自己操的)哈哈。。。。

猜你喜欢

转载自blog.csdn.net/qq_32648731/article/details/78041363