0.      写在最前面

本人參考安晓辉大侠的一篇博文后。做了Qt on android的GSP相关的实验。为了后面不时之需。故而记录下来。

1.      Qt on Android GPS系统流程

图1. 系统流程图

如图1所看到的,系统含两个层面:其一为基于QT的UI。提供启动GPS的button(QPushButton)。以及显示GPS信号的文本域(QTextBrowser)。其二为基于Activity的GPS服务,提供GPS的启动,GPS信号上报等服务。两个层面的交互及C++与Java的交互通过JNI来实现。

系统的总体线索如箭头方式所看到的:在QT层,button被点击后。槽函数startGps被触发。该函数调用Activity层的方法calledByCpp,而calledByCpp方法发送消息到mes handle,消息类型为MSG_STR_GPS_LOC。handle收到消息后。调用函数startAmap启动GPS的定位。GPS启动后,位置的实时信息在函数onLocationChanged()函数中公布,该函数把位置信息通过消息发送给msg
handle,当中消息类型为MSG_RPT_GSP_INF。handle再调用native方法reportGpsInfo,就能够把消息发送给QT层。

2.      创建Androidproject

图2 创建project

project命名为QtAndroidGps,且其路径为E:\work\c++\qt。project创建之后。文件夹结构例如以下:

图3. project初始文件

在上述自己主动生成文件夹下增加文件夹android:

图4. 增加目录android后

目录android里面包括例如以下内容:

图5. 目录android的内容

能够看出,文件夹结构与通过eclipse生成的android工程类似,少了assets。bin,gen,res等文件夹,以及project.properties等文件。

本project可採用百度与高德的库来定位。其相关的jar包分别为BaiduLBS_Android.jar与Android_Location_V1.1.2.jar。这两个包均放入到e:\work\c++\qt\QtAndroid\android\libs。

同一时候。在构建projectQtAndroidGps之后,qt会在路径e:\work\c++\qt\之下自己主动生成文件夹:

E:\work\c++\qt\build-QtAndroidGps-Android_for_armeabi_v7a_GCC_4_8_Qt_5_4_0-Debug,该文件夹包括下面文件:

图6. qt构建project后生成的project文件夹

当中,android-build文件夹包括qt构建出来的androidproject,该project即为完整的androidproject:

图7. qt构建project后生成的androidproject文件夹

能够发现,之前我们人为创建的projecte:\work\c++\qt\QtAndroid\android\里面的文件除了AnroidManifest.xml被整合外,其它文件包含jar包和java文件都被拷贝入:

build-QtAndroidGps-Android_for_armeabi_v7a_GCC_4_8_Qt_5_4_0-Debug。

3.      project文件清单

3.1 E:\work\c++\qt\QtAndroidGps\android\AndroidManifest.xml

......

图8. AndroidManifest.xml

该文件有如上图标注的4个重要点:

①  ->与E:\work\c++\qt\QtAndroidGps\android\src中java文件的包路径相应

②  ->要把百度与高德的包用起来。必须增加Api-key

③  ->相应Activity的类名

④  ->须要开启GPS定位相关的权限

3.2.1 E:\work\c++\qt\QtAndroidGps\mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H #include <QMainWindow>
#include <QPushButton> namespace Ui {
class MainWindow;
} class MainWindow : public QMainWindow
{
Q_OBJECT public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow(); protected:
bool event(QEvent *e); private:
Ui::MainWindow *ui;
QPushButton *btn; // 点击启动GPS private slots:
void startGps(); // btn相应的点击槽函数 }; #endif // MAINWINDOW_H

3.2.2 E:\work\c++\qt\QtAndroidGps\mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QAndroidJniObject>
#include "CustomEvent.h" MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
btn = new QPushButton("start", this);
btn->setGeometry(QRect(10, 10, 100, 50));
connect(btn, SIGNAL(clicked()), this, SLOT(startGps()));
} MainWindow::~MainWindow()
{
delete ui;
} void MainWindow::startGps()
{
//QAndroidJniObject javaAction = QAndroidJniObject::fromString(url);
QAndroidJniObject::callStaticMethod<void>( /* 调用java方法,具体情况请參考qt的帮助文档 */
"com/mtn/mes/GpsService",
"calledByCpp",
"()V"); } bool MainWindow::event(QEvent *e)
{
if(e->type() == CustomEvent::eventType()){ /* 匹配上自己定义事件类型 */
e->accept();
CustomEvent *sce = (CustomEvent*)e;
//_resultView->setText(sce->m_arg2);
ui->textBrowser->setText(sce->m_arg2); /* 显示GPS信息 */
return true;
}
return QWidget::event(e);
}

3.3.1 E:\work\c++\qt\QtAndroidGps\CustomEvent.h

#ifndef CUSTOMEVENT_H
#define CUSTOMEVENT_H
#include <QEvent>
#include <QString> class CustomEvent : public QEvent
{
public:
CustomEvent(int arg1 = 0, const QString &arg2 = QString());
~CustomEvent(); static Type eventType(); int m_arg1;
QString m_arg2; private:
static Type m_evType;
}; #endif // CUSTOMEVENT_H

3.3.2 E:\work\c++\qt\QtAndroidGps\CustomEvent.cpp

#include "CustomEvent.h"

QEvent::Type CustomEvent::m_evType = (QEvent::Type)QEvent::None;

CustomEvent::CustomEvent(int arg1, const QString &arg2)
: QEvent(eventType()), m_arg1(arg1), m_arg2(arg2)
{} CustomEvent::~CustomEvent()
{ } QEvent::Type CustomEvent::eventType()
{
if(m_evType == QEvent::None)
{
m_evType = (QEvent::Type)registerEventType(); /* 注冊自己定义事件,返回m_evType值为qt分配的自己定义事件类型 */
}
return m_evType;
}

3.4 E:\work\c++\qt\QtAndroidGps\CustomEvent.cpp

#include "mainwindow.h"
#include <QApplication>
#include <QDebug>
#include <jni.h>
#include <QAndroidJniEnvironment>
#include <QAndroidJniObject>
#include "CustomEvent.h" QObject *main_window = 0;
/* 该函数被java的本地方法调用 */
static void reportGpsInfo(JNIEnv *env, jobject thiz,int result, jstring data)
{
QString qstrData;
const char *nativeString = env->GetStringUTFChars(data, 0);
qstrData = nativeString;
env->ReleaseStringUTFChars(data, nativeString);
QCoreApplication::postEvent(main_window, new CustomEvent(result, qstrData)); /* 发送事件(携带GPS信息)给主窗体。自己定义事件类型 */
qDebug() << qstrData;
} bool registerNativeMethods()
{
JNINativeMethod methods[] {
{"reportGpsInfo", "(ILjava/lang/String;)V", (void*)reportGpsInfo} /* 注冊本地方法,java方可调用,具体信息见qt帮助文档 */
}; const char *classname = "com/mtn/mes/ExtendsQtNative";
jclass clazz;
QAndroidJniEnvironment env;
QAndroidJniObject javaClass(classname);
clazz = env->GetObjectClass(javaClass.object<jobject>());
qDebug() << "find ExtendsQtNative - " << clazz; bool result = false;
if(clazz) {
jint ret = env->RegisterNatives(clazz, methods, sizeof(methods) / sizeof(methods[0]));
env->DeleteLocalRef(clazz);
qDebug() << "RegisterNatives return - " << ret;
result = ret >= 0;
}
if(env->ExceptionCheck()) env->ExceptionClear();
return result;
} int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
CustomEvent::eventType(); // 注冊自己定义事件,生成自己定义事件类型
registerNativeMethods(); // 注冊本地方法
w.show();
main_window = qobject_cast<QObject*>(&w);
return a.exec();
}

3.5 E:\work\c++\qt\QtAndroidGps\android\src\com\mtn\mes\ExtendsQtNative.java

package com.mtn.mes;
import java.lang.String; public class ExtendsQtNative
{
public native void reportGpsInfo(int result, String content);
}

3.6 E:\work\c++\qt\QtAndroidGps\android\src\com\mtn\mes\GpsService.java

package com.mtn.mes;
import java.lang.String;
import android.content.Context;
import android.content.Intent;
import android.app.PendingIntent;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.location.Criteria;
import android.provider.Settings;
import android.os.Bundle;
import android.os.Environment;
import java.io.File;
import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.AsyncHttpResponseHandler;
import android.widget.Toast;
import java.util.Date; import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationListener;
import com.amap.api.location.LocationManagerProxy;
import com.amap.api.location.LocationProviderProxy;
import com.baidu.location.BDLocation;
import com.baidu.location.BDLocationListener;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.baidu.location.LocationClientOption.LocationMode; public class GpsService extends org.qtproject.qt5.android.bindings.QtActivity
{
private static GpsService m_instance;
private final static String TAG = "GpsService";
private final static int MSG_STR_GPS_LOC = 0;
private final static int MSG_RPT_GPS_INF = 1; ////////////////////////////////////////////////////////////////
// 定位相关
////////////////////////////////////////////////////////////////
private LocationManagerProxy aMapManager; public GpsService(){
m_instance = this;
} public static void calledByCpp() {
System.out.println("[0]hello world!");
Message msg = new Message();
msg.what = MSG_STR_GPS_LOC;
m_instance.handler.sendMessage(msg); // 消息触发,启动GPS定位
//m_instance.handler.sendEmptyMessage(0); // 消息触发。启动GPS定位
} public static void calledByCpp(int arg0) {
System.out.println("[1]hello world!");
} private void startAmap() {
aMapManager = LocationManagerProxy.getInstance(this);
/*
* mAMapLocManager.setGpsEnable(false);
* 1.0.2版本号新增方法,设置true表示混合定位中包括gps定位,false表示纯网络定位,默认是true Location
* API定位採用GPS和网络混合定位方式
* ,第一个參数是定位provider,第二个參数时间最短是2000毫秒,第三个參数距离间隔单位是米,第四个參数是定位监听者
*/
aMapManager.requestLocationUpdates(LocationProviderProxy.AMapNetwork, 2000, 10, mAMapLocationListener);
} private AMapLocationListener mAMapLocationListener = new AMapLocationListener() { @Override
public void onStatusChanged(String provider, int status, Bundle extras) { } @Override
public void onProviderEnabled(String provider) { } @Override
public void onProviderDisabled(String provider) { } @Override
public void onLocationChanged(Location location) { } @Override
public void onLocationChanged(AMapLocation location) {
if (location != null) {
Double geoLat = location.getLatitude();
Double geoLng = location.getLongitude();
String cityCode = "";
String desc = "";
Bundle locBundle = location.getExtras();
if (locBundle != null) {
cityCode = locBundle.getString("citycode");
desc = locBundle.getString("desc");
} String str = (
"location ok:(" + geoLng + "," + geoLat + ")"+
"\nAccuracy :" + location.getAccuracy() + "Meter" +
"\nPositioning:" + location.getProvider() +
"\nPositioning time:" + new Date(location.getTime()).toLocaleString() +
"\nCity coding :" + cityCode +
"\nLocation Description:" + desc +
"\nProvince:" + location.getProvince() +
"\nCity:" + location.getCity() +
"\nDistrict (county):" + location.getDistrict() +
"\nRegional Coding:" + location.getAdCode()); //Toast.makeText(getApplicationContext(), "高德定位\n" + str, Toast.LENGTH_SHORT).show(); // 发送位置信息到handler, hander处再转发给Qt
Message msg = new Message();
Bundle data = new Bundle();
data.putString("value", str);
msg.setData(data);
msg.what = MSG_RPT_GPS_INF;
handler.sendMessage(msg);
}
}
}; private Handler handler = new Handler() { @Override
public void handleMessage(Message msg) {
switch(msg.what) {
case MSG_STR_GPS_LOC: // 消息类型为启动GPS定位
m_instance.startAmap();
break; case MSG_RPT_GPS_INF: // 消息类型为上送GSP信息
ExtendsQtNative m_nativeNotify = new ExtendsQtNative();
Bundle data = msg.getData();
System.out.println(data.getString("value"));
m_nativeNotify.reportGpsInfo(0, data.getString("value")); // 掉用c++方法
break; default:
System.out.println("msg type error!");
break;
}
}
};
}

点击下载源代码

qt on android之GPS信号的获取的更多相关文章

  1. [置顶] xamarin android使用gps定位获取经纬度

    看了文章你会得出以下几个结论 1.android定位主要有四种方式GPS,Network(wifi定位.基站定位),AGPS定位 2.绝大部分android国产手机使用network进行定位是没有作用 ...

  2. Qt on Android 核心编程

    Qt on Android 核心编程(最好看的Qt编程书!CSDN博主foruok倾力奉献!) 安晓辉 著   ISBN 978-7-121-24457-5 2015年1月出版 定价:65.00元 4 ...

  3. 创建一个QT for Android的传感器应用应用程序(摘自笔者2015年将出的《QT5权威指南》,本文为试读篇)

     这个手册描述了使用Qt Quick面访的方式在Android和ios设备上开发QtQuick应用程序的方法.我们使用Qt Creator实现一个QtQuick应用程序,这个应用程序基于加速器的值 ...

  4. Qt on Android: http下载与Json解析

    百度提供有查询 ip 归属地的开放接口,当你在搜索框中输入一个 ip 地址进行搜索,就会打开由 ip138 提供的百度框应用,你能够在框内直接输入 ip 地址查询.我查看了页面请求,提取出查询 ip ...

  5. Qt on Android 蓝牙开发

    版权声明:本文为MULTIBEANS ORG研发跟随文章,未经MLT ORG允许不得转载. 最近做项目,需要开发安卓应用,实现串口的收发,目测CH340G在安卓手机上非常麻烦,而且驱动都是Java版本 ...

  6. 对Qt for Android的评价(很全面,基本已经没有问题了,网易战网客户端就是Qt quick写的),可以重用QT积累20年的RTL是好事,QML效率是HTML5的5倍

    现在Qt不要光看跨平台了,Qt也有能力和原生应用进行较量的.可以直接去Qt官网查看他和那些厂商合作.关于和Java的比较,框架和Java进行比较似乎不且实际.如果是C++和Java比较,网上有很多文章 ...

  7. 《Qt on Android核心编程》夹

    china-pub在售前,售中环节退房,折扣低! 有朋友想看看<Qt on Android核心编程>的文件夹,So-- 文件夹     <Qt on Android核心编程>文 ...

  8. Qt on Android: Qt 5.3.0 公布,针对 Android 改进的说明

    5月20日本,Qt 官方博客宣布 Qt 5.3.0 公布! 这个版本号聚焦在性能.稳定性和可用性的提升上,与 5.1 / 5.2 相比有非常大提升. 5.3.0 的主要变化: 稳定能.可用性大大提升 ...

  9. 《Qt on Android核心编程》介绍

    <Qt on Android核心编程>最终尘埃落定.付梓印刷了. 2014-11-02更新:china-pub的预售链接出来了.折扣非常低哦. 封面 看看封面的效果吧,历经几版,最终就成了 ...

随机推荐

  1. Vue电商SKU组合算法问题

    前段时间,公司要做“添加商品”业务模块,这也算是电商业务里面的一个难点了. 令我印象最深的不是什么“组合商品”.“关联商品”.“关联单品”,而是商品SKU的组合问题. 这个问题特别有意思,当时虽然大体 ...

  2. BZOJ 4811 树链剖分+线段树

    思路: 感觉这题也可神了.. (还是我太弱) 首先发现每一位不会互相影响,可以把每一位分开考虑,然后用树链剖分或者LCT维护这个树 修改直接修改,询问的时候算出来每一位填0,1经过这条链的变换之后得到 ...

  3. action="post" 、 servletconfig 、 servletcontext 、getPrintWiter() 、context-param、 init-param(第一个完整的servlet)

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <hea ...

  4. Mediacodec编码后的h264视频出现马赛克问题

    问题:在视频采集后,通过Mediacodec编码生成h264视频文件,播放时出现马赛克较多,无论调整帧率.码率.还是分辨率都不能解决问题 出现问题的原因:编码时传入的时间戳不对.时间戳是视频播放的标准 ...

  5. 屏蔽scrollview的滚动

    外层有scrollview时,手指移动方向跟滚动条方向相同时,会导致scrollview的滚动.此时如果不想滚动的话,可以在要接受ontouch的子视图,或者子子视图中的touch监听里加上v.get ...

  6. html5——渐变

    线性渐变 <style> div { width: 700px; height: 100px; /*方向:从右向左*/ /*起始颜色:黄色*/ /*终止颜色:绿色*/ background ...

  7. jdbc 使用谨记

    jdbc是java操作数据库的杀手锏.所有java程序员,对jdbc应该都不陌生. 但是,应该你也曾经被其折磨的抓耳挠腮,咬牙切齿吧,也许正因为这样你才对其记忆犹新,刻骨铭心. 这里有一些使用jdbc ...

  8. 白盒-CNN纹理深度可视化: 使用MIT Place 场景预训练模型

    MIT发文:深度视觉的量化表示................ Places2 是一个场景图像数据集,包含 1千万张 图片,400多个不同类型的场景环境,可用于以场景和环境为应用内容的视觉认知任务. ...

  9. Python 之selenium+phantomJS斗鱼抓取案例

    from selenium import webdriver from bs4 import BeautifulSoup import time if __name__ == '__main__': ...

  10. 原生js实现瀑布流效果

    参考此篇:https://segmentfault.com/a/1190000012621936 以下为个人测试中: css: .masonry{ width:100%; } .item{ posit ...