转转上买来的斐讯n1天天链,刷了webpad官改系统当电视盒子用,在手机上安装斐讯官方的遥控app后,可以替代实体遥控器,实现遥控电视盒子的功能,少掏30-40购买遥控器的钱。但是美中不足的是,盒子一旦关机就无法开机,必须重新插拔电源才能开机,很不方便。于是开始研究如何用软件遥控盒子开关机的办法。
n1没有红外功能,所以遥控器一般都是通过蓝牙或者wifi来连接的。本文介绍的是wifi遥控,蓝牙遥控见我的另一篇文章斐讯n1遥控器app——蓝牙篇。由于手上没有t1遥控器,不清楚使用实体遥控器能不能开机,如果能开机,开机的原理又是什么?盒子关机后蓝牙和wifi都断开了,如何唤醒?网上有资料说,可以通过蓝牙发送广播数据包或者通过以太网发送幻数据包的方式使盒子开机,前者由于需要对蓝牙协议比较熟悉,太过复杂,只好放弃,后者经测试无效。
后来想到官改系统已经具有了root权限,而且开放了telnet服务(端口号为2323),完全可以使用Linux命令实现关机。
基本思路就是用java编写telnet客户端,远程登录到电视盒子上,执行
echo mem > /sys/power/state
命令(具体介绍请百度“安卓电源管理”)关闭屏幕,注意这里只是休眠,wifi仍连接着,并不是关机,要是真的关机就没办法唤醒了!虽然这个办法也不是那么完美,但是毕竟省去了拔电源的苦恼,而且n1待机状态下耗电量很小,可以忽略。
想要亮屏的话执行下面的命令即可
echo "mem disk" > /sys/power/state
为了把休眠和唤醒的功能加到遥控器里,需要先分析一下官方原版遥控的实现原理
通过使用charles抓包工具进行分析,可以发现官方遥控app其实就是向盒子上的服务端发送简单的http请求。下面是使用jadx反编译后看到的部分源码,正好对应了app里的部分功能。
public interface IRemoterService {
b doScreenshot();//截屏
b getStatus();//获取盒子的名称、mac等信息
b ping();//ping测试
b sendCommand(String str);//发送命令,比如打开设置界面
b sendKeyEvent(KeyEvent keyEvent);//发送按键
}
public interface HttpAppInfosService {
@GET("applist")
b getAppInfos();//获取已安装的应用列表
@POST("application")
@Headers({"Content-Type:application/json;charset=UTF-8"})
b openApplication(@Body z zVar);//打开应用
}
以下假设盒子内网地址为192.168.123.116
接口地址:http://192.168.123.116:8080/v1/keyevent
请求方法:POST
参数:{"keycode":4,"longclick":false}
public class KeyCode {
public static int BACK = 4;
public static int CENTER = 23;
public static int CHANEL_DOWN = 167;
public static int CHANEL_UP = 166;
public static int DOWN = 20;
public static int HOME = 3;
public static int LEFT = 21;
public static int MENU = 82;
public static int MUTE = 164;
public static int POWER = 26;
public static int RIGHT = 22;
public static int UP = 19;
public static int VOL_DOWN = 25;
public static int VOL_UP = 24;
}
接口地址:http://192.168.123.116:8080/v1/action
请求方法:POST
参数:{"action":"setting"}
public class Commands {
public static String OPEN_CLEAR = "openclear";//打开电视管家一键清理
public static String OPEN_LOCK = "openlock";//儿童锁
public static String OPEN_SETTING = "setting";//设置
}
接口地址:http://192.168.123.116:8080/v1/ping
请求方法:GET
接口地址:http://192.168.123.116:8080/v1/status
请求方法:GET
接口地址:http://192.168.123.116:8080/v1/applist
请求方法:GET
接口地址:http://192.168.123.116:8080/v1/application
请求方法:POST
参数:{"package":"com.android.tv.settings","activity":"com.android.tv.settings.MainSettings"}
包名和activity名参照上一个接口的返回结果
接口地址:http://192.168.123.116:8080/v1/screenshot
请求方法:GET
本想着自己重新开发一个app实现需求,但是发现github上已经有人做过了,于是就直接把源码拿来用了,把原来的项目里关机键的逻辑稍微改动一下就行了。java版的telnet客户端例子网上也有一大把,不过感觉对socket粘包、半包等问题的处理都不太优美,如果只关心发送命令而不关心命令执行结果的话,也可以直接拿来用。
附上别人做好的遥控器app(关机后不能唤醒):
斐讯/PHICOMM N1 盒子YYF电视盒子的遥控器(android版本):https://github.com/Jimmuy/N1_controler
由于本人代码水平比较烂,修改后的代码就不放上来了,这里仅仅提供一个思路。下图是修改后的效果。
没有悟空遥控器烦人的广告,而且比官方遥控器启动更快,更加地简洁,自用已经足够了。