我们要实现手机app遥控看电视,分为俩个步骤:1写服务器端app,安装于讯为4412开发板,2写手机客户端,用于控制遥控
1 服务端,新建一个空工程,想要实现app开机自动启动,需要实现拦截广播android.permission.RECEIVE_BOOT_COMPLETED,并且需要使用静态注册广播的方法(即在AndroidManifest.xml文件中定义广播)代码如下:
在AndroidManifast.xml中添加权限,并注册一个receiver
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="cn.stu.remote">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<service
android:name=".RemoteService"
android:enabled="true"
android:exported="true"></service>
//注册receiver
<receiver android:name=".MyReceiver">
<intent-filter>
<action android:name="cn.stu.remote.HELLOWORLD" />
</intent-filter>
</receiver>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
上面的MyReceiver是我自己写的类,继承了BroadcastReceiver的,代码如下
package cn.stu.remote;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class MyReceiver extends BroadcastReceiver {
private static final String TAG = "BroadcastReceiver";
@Override
public void onReceive(Context context, Intent intent) {
// TODO: This method is called when the BroadcastReceiver is receiving
// an Intent broadcast.
Intent startIntent = new Intent(context, RemoteService.class);
context.startService(startIntent);
Log.i(TAG, "BroadcastReceiver");
}
}
以下是MainActivity类的代码
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toast.makeText(this, "哈哈,我成功启动了!", Toast.LENGTH_LONG).show();
Log.e("AutoRun","哈哈,我成功启动了!");
}
接下来实现广播
需在AndroidManifest.xml添加广播静态配置,中添加需要监听的广播类型
因为我们要调用本地库,先写一个native-lib.cpp
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//模拟按键
int simulate_key(int fd,int kval)
{
struct input_event event;
event.type = EV_KEY;
event.value = 1;
event.code = kval;
gettimeofday(&event.time,0);
write(fd,&event,sizeof(event)) ;
event.type = EV_SYN;
event.code = SYN_REPORT;
event.value = 0;
write(fd, &event, sizeof(event));
memset(&event, 0, sizeof(event));
gettimeofday(&event.time, NULL);
event.type = EV_KEY;
event.code = kval;
event.value = 0;
write(fd, &event, sizeof(event));
event.type = EV_SYN;
event.code = SYN_REPORT;
event.value = 0;
write(fd, &event, sizeof(event));
return 0;
}
extern "C" JNIEXPORT jint JNICALL
Java_cn_stu_remote_NativeLib_pressKey(JNIEnv* env,jobject obj,jint key)
{
int fd_kbd;
//打开串口
fd_kbd = open("/dev/input/event2",O_RDWR);
if(fd_kbd<=0){
__android_log_print(ANDROID_LOG_ERROR, "serial", "error open keyboard:\n");
//printf( "error open keyboard:\n");
return -1;
}
simulate_key(fd_kbd, key );
close(fd_kbd);
__android_log_print(ANDROID_LOG_ERROR, "serial", "点击了按键%d",key);
//printf("点击了按键%d",key);
return 0;
}
创建一个本地库类class
package cn.stu.remote;
public class NativeLib {
public native int pressKey(int key);
}
再回mainactivity.java里实例化一个本地库
nativeLib = new NativeLib();
RemoteService.java
package cn.stu.remote;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
public class RemoteService extends Service {
private static final String TAG = "notice";
private static final int BROADCAST_PORT = 8080;
private DatagramSocket receiveSocket = null;
private ReceiveThread receiveThread;
private static final int KEY_UP = 103;
private static final int KEY_LEFT = 105;
private static final int KEY_RIGHT = 106;
private static final int KEY_DOWN = 108;
private static final int KEY_ENTER = 28;
private static final int KEY_POWER = 116;
private static final int KEY_VOLUMEDOWN = 114;
private static final int KEY_VOLUMEUP = 115;
private static final int KEY_ESC = 1;
private static final int KEY_MENU = 82;
private static final int KEY_BACK = 158;
/* private static String IP;
private static int BROADCAST_PORT = 9999;
private static String BROADCAST_IP = "255.255.255.255";*/
/*
private InetAddress inetAddress = null;
*/
public RemoteService() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
return null;
}
@Override
public void onCreate() {
try {
//创建一个DatagramSocket实例,并将该对象绑定到本机默认IP地址、本机所有可用端口中随机选择的某个端口。
receiveSocket = new DatagramSocket(new InetSocketAddress(BROADCAST_PORT));
//hreadReceive 是实力化出的一个线程对象
receiveThread = new ReceiveThread();
receiveThread.start();//开启进程
} catch (SocketException e) {
e.printStackTrace();
}
Toast.makeText(this, "My Service created", Toast.LENGTH_LONG).show();
Log.i(TAG, "onCreate");
}
@Override
public void onDestroy() {
Toast.makeText(this, "My Service Stoped", Toast.LENGTH_LONG).show();
Log.i(TAG, "onDestroy");
if(receiveSocket != null && !receiveSocket.isClosed())
{
receiveSocket.close();
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// do your jobs here
return super.onStartCommand(intent, flags, startId);
}
private class ReceiveThread extends Thread {
@Override
public void run() {
while (true) {
byte[] receiveData = new byte[1024];
DatagramPacket dpReceive = null;
dpReceive = new DatagramPacket(receiveData, receiveData.length);
try {
Log.i(TAG, "开始接收数据" );
receiveSocket.receive(dpReceive);
String KeyEvent = new String(dpReceive.getData(), 0, dpReceive.getLength(), StandardCharsets.UTF_8);
NativeLib nativeLib = new NativeLib();
Log.i(TAG, "receive data " + KeyEvent);
switch (KeyEvent){
case "KEY_UP":
nativeLib.pressKey(KEY_UP);
break;
case "KEY_LEFT":
nativeLib.pressKey(KEY_LEFT);
break;
case "KEY_RIGHT":
nativeLib.pressKey(KEY_RIGHT);
break;
case "KEY_DOWN":
nativeLib.pressKey(KEY_DOWN);
break;
case "KEY_ENTER":
nativeLib.pressKey(KEY_ENTER);
break;
case "KEY_POWER":
nativeLib.pressKey(KEY_POWER);
break;
case "KEY_VOLUMEUP":
nativeLib.pressKey(KEY_VOLUMEUP);
break;
case "KEY_VOLUMEDOWN":
nativeLib.pressKey(KEY_VOLUMEDOWN);
break;
case "KEY_MENU":
nativeLib.pressKey(KEY_MENU);
break;
case "KEY_BACK":
nativeLib.pressKey(KEY_BACK);
break;
case "KEY_ESC":
nativeLib.pressKey(KEY_ESC);
break;
}
} catch (IOException e) {
e.printStackTrace();
}
/*
String recIp = dpReceive.getAddress().toString().substring(1);
*/
}
}
}
}
好了,完成服务器端,下篇写客户端