原文地址:http://blog.starrtc.com/?p=111

这篇来介绍一下整个项目的手机端部分。在上一篇里我们已经将sdk导入到项目中了,下边直接用即可。

1 登录StarRTC的服务
跟小车端一样,第一步需要初始化StarRTCsdk并登录到StarRTC的服务。
跟小车端不同的是,手机端初始化SDK时,不需要设置一些特殊的默认值,小车端是为了适配树莓派才进行了特殊配置。
还有手机端要加动态权限申请。

MLOC.userId = "driver"+ new Random().nextInt(100)+ new Random().nextInt(100);
XHClient.getInstance().initSDK(this, new XHSDKConfig(MLOC.agentId),MLOC.userId);
XHClient.getInstance().getChatManager().addListener(new XHChatManagerListener());
XHClient.getInstance().getLoginManager().addListener(new XHLoginManagerListener());

在确认申请的权限已经得到授权后,可以开始执行登录流程。
首先获取登录授权码AuthKey,然后登录到StarRTC的服务。

    private int times = 0;
private final int REQUEST_PHONE_PERMISSIONS = 0;
private void checkPermission(){
times++;
final List permissionsList = new ArrayList<>();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
if ((checkSelfPermission(Manifest.permission.READ_PHONE_STATE)!= PackageManager.PERMISSION_GRANTED)) permissionsList.add(Manifest.permission.READ_PHONE_STATE);
if ((checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED)) permissionsList.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
if ((checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED)) permissionsList.add(Manifest.permission.READ_EXTERNAL_STORAGE);
if ((checkSelfPermission(Manifest.permission.CAMERA)!= PackageManager.PERMISSION_GRANTED)) permissionsList.add(Manifest.permission.CAMERA);
if ((checkSelfPermission(Manifest.permission.BLUETOOTH)!= PackageManager.PERMISSION_GRANTED)) permissionsList.add(Manifest.permission.BLUETOOTH);
if ((checkSelfPermission(Manifest.permission.RECORD_AUDIO)!= PackageManager.PERMISSION_GRANTED)) permissionsList.add(Manifest.permission.RECORD_AUDIO);
if (permissionsList.size() != 0){
if(times==1){
requestPermissions(permissionsList.toArray(new String[permissionsList.size()]),
REQUEST_PHONE_PERMISSIONS);
}else{
new android.support.v7.app.AlertDialog.Builder(this)
.setCancelable(true)
.setTitle("提示")
.setMessage("获取不到授权,APP将无法正常使用,请允许APP获取权限!")
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface arg0, int arg1) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(permissionsList.toArray(new String[permissionsList.size()]),
REQUEST_PHONE_PERMISSIONS);
}
}
}).setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface arg0, int arg1) {
finish();
}
}).show();
}
}else{
startAnimation();
InterfaceUrls.demoLogin(MLOC.userId);//获取登录授权码
}
}else{
startAnimation();
InterfaceUrls.demoLogin(MLOC.userId);//获取登录授权码
}
} @Override
public void onRequestPermissionsResult(int requestCode, @NonNull final String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
checkPermission();
}
@Override
public void dispatchEvent(String aEventID, boolean success, Object eventObj) {
switch (aEventID){
case AEvent.AEVENT_LOGIN:
//拿到登录授权码,开始登录StarRTC服务
if(success){
MLOC.d("", (String) eventObj);
XHClient.getInstance().getLoginManager().login(MLOC.authKey, new IXHCallback() {
@Override
public void success(Object data) {
isLogin = true;
} @Override
public void failed(final String errMsg) {
MLOC.d("",errMsg);
runOnUiThread(new Runnable() {
@Override
public void run() {
MLOC.showMsg(SplashActivity.this,errMsg);
}
});
}
});
}else{
MLOC.d("", (String) eventObj);
}
break;
case AEvent.AEVENT_C2C_REV_MSG:
runOnUiThread(new Runnable() {
@Override
public void run() {
MLOC.showMsg(SplashActivity.this,"小车已经启动");
}
});
XHIMMessage message = (XHIMMessage) eventObj;
//收到消息,并确认是小车发来的,消息内容为小车创建的直播间ID
if(message.fromId.equals(waitCarId)){
Intent intent = new Intent(SplashActivity.this, VideoLiveActivity.class);
intent.putExtra(VideoLiveActivity.LIVE_ID,message.contentData);
intent.putExtra(VideoLiveActivity.LIVE_NAME,waitCarId);
intent.putExtra(VideoLiveActivity.CREATER_ID,waitCarId);
startActivity(intent);
removeListener();
finish();
}
break;
}
}

登录成功后的界面是这样的

2 与小车建立连接
登录成功后,手机端就可以给小车发启动指令了。这里指定的启动指令为“IotCarStart”,启动指令发送成功后,手机端等待小车端的回复,正常情况下,小车收到指令后会创建互动直播间,并将创建好的直播间ID通过IM消息发送给手机端,手机端再通过互动直播ID进入小车创建的房间,进入房间后再申请连麦,小车会自动通过手机端的申请,至此小车和手机端建连成功。

private void joinLive(){
//加入直播
liveManager.watchLive(liveId, new IXHCallback() {
@Override
public void success(Object data) {
//加入直播成功后,自动申请连麦
liveManager.applyToBroadcaster(createrId);
}
@Override
public void failed(final String errMsg) {
d("XHLiveManager","watchLive failed "+errMsg);
runOnUiThread(new Runnable() {
@Override
public void run() {
showMsg(VideoLiveActivity.this,errMsg);
removeListener();
finish();
}
}); }
});
}
@Override
public void dispatchEvent(String aEventID, boolean success, final Object eventObj) {
d("XHLiveManager","dispatchEvent "+aEventID + eventObj);
switch (aEventID){
case AEvent.AEVENT_LIVE_ADD_UPLOADER:
try {
JSONObject data = (JSONObject) eventObj;
final String addId = data.getString("actorID");
runOnUiThread(new Runnable() {
@Override
public void run() {
if(addId.equals(createrId)){
liveManager.attachPlayerView(addId,player1,true);
}
}
});
} catch (JSONException e) {
e.printStackTrace();
}
break;
case AEvent.AEVENT_LIVE_REMOVE_UPLOADER:
stop();
break; case AEvent.AEVENT_LIVE_APPLY_LINK_RESULT:
//申请连麦后,收到小车的回复
if(eventObj== XHConstants.XHLiveJoinResult.XHLiveJoinResult_accept){
//切换角色,开始连麦
liveManager.changeToBroadcaster();
}
break; case AEvent.AEVENT_LIVE_ERROR:
runOnUiThread(new Runnable() {
@Override
public void run() {
String errStr = (String) eventObj;
showMsg(getApplicationContext(),errStr);
removeListener();
startActivity(new Intent(VideoLiveActivity.this, SplashActivity.class));
finish();
}
});
break;
}
}

建立链接成功后,将能看到小车采集到的实时画面。

3 给小车发送指令
从操控界面可以看到,左边上下左右有四个按钮,这四个按钮是控制小车运动方向的。
右边有个360度的方向舵,这个是控制小车上云台转动方向的。
左上有个红色的关闭按钮,点击可以停止对小车的操控。
右上有个绿色复位按钮,点击可以使摄像头云台恢复到默认状态,朝向车身正前方。
小车的运动指令有6个:up(前)、down(后)、left(左)、right(右)、start(电机启动)、stop(电机停止)。
每次按下一个方向的按钮时(以up为例),连续发送两个指令 start + up,小车启动并向前,手指从按钮抬起时发送一个指令 stop,小车将停止运动。
云台的运动指令有10个:camera++、camera+-、camera+=、camera-+、camera–、camera-=、camera=+、camera=-、camera==、cameraReset。
其中“+”代表舵机度数增加,“-”代表舵机度数减小,“=”代表舵机度数不变,cameraReset是命令云台复位。
手指触碰方向舵时,会根据触碰的位置不通发送不通的指令,云台的两个舵机会根据指令进行角度调整,手指从方向舵拿开时,会发送camera==,云台停止调整并保持当前的角度,直至收到下一个操控云台的指令。

多说几句,可能是不同舵机的具体情况不一样,我这里写的可能只适用于我的这个小车程序,即便是我自己的程序,舵机的表现也是前后不一的,刚完成的时候,舵机的运动很流畅,但是玩了这么就之后,舵机操作开始有卡顿和颤抖的情况,可能老化了,毕竟是最便宜的小玩应儿,就不强求了。

好了,远程视频遥控小车的相关介绍就到这里了,希望能对大家有所帮助。谢谢观看。

同行的认可是远行最大的动力,欢迎转载本博客文章,转载请注明出处,十分感谢。

StarRTC , AndroidThings , 树莓派小车,公网环境,视频遥控(一)准备工作
StarRTC , AndroidThings , 树莓派小车,公网环境,视频遥控(二)小车端
StarRTC , AndroidThings , 树莓派小车,公网环境,视频遥控(三)手机端
源码下载地址

StarRTC , AndroidThings , 树莓派小车,公网环境,视频遥控(三)手机端的更多相关文章

  1. StarRTC , AndroidThings , 树莓派小车,公网环境,视频遥控(二)小车端

    原文地址:http://blog.starrtc.com/?p=94 1 创建工程IDE:Android Studio 3.1:File>New>New Project>输入项目名& ...

  2. StarRTC , AndroidThings , 树莓派小车,公网环境,视频遥控(一)准备工作

    原文地址:http://blog.starrtc.com/?p=48 啥也不说,先来个视频看看效果 视频播放器     00:00   00:54     概述为了体现StarRTC的实时音视频传输能 ...

  3. H.264视频在android手机端的解码与播放(转)

    随着无线网络和智能手机的发展,智能手机与人们日常生活联系越来越紧密,娱乐.商务应用.金融应用.交通出行各种功能的软件大批涌现,使得人们的生活丰富多彩.快捷便利,也让它成为人们生活中不可取代的一部分.其 ...

  4. 【树莓派+.NET MF打造视频监控智能车】遥控篇

    树莓派是最近比较火热的开源硬件,其设备只有信用卡大小,运行着Linux系统,专为学生编程教育而设计.我十多年的技术路线基本以学习微软的技术为主,中间也曾试图学习过linux,但是相对陡峭的学习曲线,只 ...

  5. 【树莓派+.NET MF打造视频监控智能车】控制篇(树莓派)

    对已经具备一定Linux基础的人来说,树莓派学习起来应该非常简单自然.在他们眼中,树莓派就是一个简易版的,卡通版的Linux而已.但是对我这样一个早已习惯微软技术生态系统的人或者初学者来说,要实现一个 ...

  6. 树莓派小车(三)Python控制小车

    正文之前 由于最近忙于复习赶考,所以暂时没有拿起树莓派小车,直到昨天,终于空出时间来把代码整理一下来和大家分享. 正文 在树莓派小车系列之二中,讲到了树莓派的引脚定义方式有两种: PHYSICAL N ...

  7. 【树莓派+.NET MF打造视频监控智能车】控制篇(.NET MF)

    在上一篇<遥控篇>文章中,我们介绍了Sony PS2手柄信号的采集和编程,通过简单的封装,以事件的方式向我们提供按键信息.本篇文章主要介绍.NET Micro Framework系统接受到 ...

  8. 个人云主机 博客上线 家用宽带-树莓派2-certbot-docker 运行环境简介

    https://blog.cuidp.top/ 博客主页,目前刚建好,没什么数据 服务是 https://github.com/TryGhost/Ghost 现插件是https://github.co ...

  9. SLAM+语音机器人DIY系列:(五)树莓派3开发环境搭建——1.安装系统ubuntu_mate_16.04

    摘要 通过前面一系列的铺垫,相信大家对整个miiboo机器人的DIY有了一个清晰整体的认识.接下来就正式进入机器人大脑(嵌入式主板:树莓派3)的开发.本章将从树莓派3的开发环境搭建入手,为后续ros开 ...

随机推荐

  1. 【Linux】撷取命令cut

    什么是撷取命令啊?说穿了,就是将一段数据经过分析后,取出我们所想要的.或者是经由分析关键词,取得我们所想要的那一行! 不过,要注意的是,一般来说,撷取信息通常是针对『一行一行』来分析的,并不是整篇信息 ...

  2. Python2 字典 has_key() 方法

    描述 Python2 字典 has_key() 方法用于判断键(key)是否存在于字典(D)中,如果键在字典中返回True,否则返回False. 官方文档推荐用 in 操作符,因为它更短更通俗易懂.h ...

  3. EF 多线程TransactionScope事务异常"事务EFTransaction类定义:与另一个进程被死锁在 锁 资源上,并且已被选作死锁牺牲品。请重新运行该事务。"

    解决方案代码一:使用lock锁定 //对于锁推荐使用静态私有静态变量 private readonly static object _MyLock = new object(); /// <su ...

  4. Sql Server添加单引号

    " ' "(单引号)的运用:在sql server中,两个" ' "(单引号)在拼接字符串的情况下运用,就是表示拼接上了一个" ' "单引号 ...

  5. vue开发环境搭建win10

    需要安装nodejs, webpack@2.2.1, babel-cli,  vue-cli 1 安装nodejs 现在版本默认会安装nodejs 和 npm包 和 配置环境 2 检查是否安装成功,在 ...

  6. 如何在virtualenv虚拟环境中安装mysql-python

    接触过virtualenv后,想在这个虚拟环境中安装独立的开发环境.在安装MySQLdb时遇到错误 pc 09:09:30 File "/home/pc/work/VENV/py3/loca ...

  7. unity, 最简单的additive shader

    Shader "Custom/myAdditive" {    Properties {                _MainTex ("Albedo (RGB)&q ...

  8. FreeBSD搭建SVN服务器

    我最喜欢使用的OS就是FreeBSD,而且现在刚好有一台FreeBSD服务器,所以我想把我的SVN服务器迁移到FreeBSD上,再配合hudson和ant就可以自动编译了. 第一步:安装svn: 在安 ...

  9. Redis(二十):Redis数据过期和淘汰策略详解(转)

    原文地址:https://yq.aliyun.com/articles/257459# 背景 Redis作为一个高性能的内存NoSQL数据库,其容量受到最大内存限制的限制. 用户在使用Redis时,除 ...

  10. Maven Docker镜像使用技巧

    摘要: Maven是目前最流行的Java项目管理工具之一,提供了强大的包依赖管理和应用构建功能.本文以Maven为例介绍了Docker在应用构建中的一些常见技巧. Maven是目前最流行的Java项目 ...