基于Qt5.3编写Android定时器
Author:AoyamaRyo
EMail:wind.river.sun@gmail.com
前言只是一个不系统的实践笔记。连门都入不了,因为本人之前并没有接触过安卓编程。所以,如有谬误,恳请指正。
缺少的东西:Manifest.xml的编写方法,Android编程的一般思路。
包含的东西:在Qt中如何使用Android的震动、顶层推送、WakeLock等。
程序是由Qt5.3中的notifier example改编而来,本文记述此过程中遇到的问题。
一、关于元对象系统
点击(此处)折叠或打开
-
QTimer *mainTimer = new QTimer(&view);
-
view.engine()->rootContext()->setContextProperty(QLatin1String("mainTimer"),
- mainTimer);
点击(此处)折叠或打开
-
Button {
-
id: btnStart
- text: qsTr("开始")
- onClicked: {
-
mw.restTimeInt = sldInterval.value*60;
- mainTimer.start(sldInterval.value*60*1000)
-
sigWakeLockAcq();
-
}
- }
Q_PROPERTY(QString notification READ notification WRITE setNotification NOTIFY sigNotificationChanged)一直以来将Qt视作一个基本C++库,所以对于Q_PROPERTY宏也为留意,但是现在看来开发QML时使用这些特性可以避免一些awkard approaches。
二、关于Android的震动、指示灯、传感器等等
这些内容并不复杂,但Qt-Project要做一个“适配尽最可能多的Android手机的库”还是需要时间打磨的。所以对于Qter,可以通过JNI自行封装相应的功能,以震动为例:
点击(此处)折叠或打开
-
package org.qtproject.example.notification;
import android.app.Notification;
import android.app.NotificationManager;
import android.content.Context;
import android.os.Bundle;
import android.app.Activity;
import android.app.Service;
import android.os.Vibrator;
import android.os.PowerManager;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Intent;
public class NotificationClient extends org.qtproject.qt5.android.bindings.QtActivity
{
private static NotificationManager m_notificationManager;
private static Notification.Builder m_builder;
private static NotificationClient m_instance;
private static Vibrator m_vibrator;
private static AlarmManager m_alarmManager;
private static PowerManager m_powerManager;
private static PowerManager.WakeLock m_wakeLock;
public NotificationClient()
{
m_instance = this;
// m_powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
// m_wakeLock = m_powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
// "MyWakelockTag");
}
public static void wakeLockAcquire(){
if(m_powerManager == null)
m_powerManager = (PowerManager)m_instance.getSystemService(Context.POWER_SERVICE);
if(m_wakeLock == null){
m_wakeLock = m_powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,"NotifierWakeLock");
}
m_wakeLock.acquire();
return;
}
public static void wakeLockRelease(){
if(m_wakeLock != null){
m_wakeLock.release();
m_wakeLock = null;
}
}
public static void notify(String s)
{
if (m_notificationManager == null) {
m_notificationManager = (NotificationManager)m_instance.getSystemService(Context.NOTIFICATION_SERVICE);
m_builder = new Notification.Builder(m_instance);
m_builder.setSmallIcon(R.drawable.icon);
m_builder.setContentTitle("A message from Qt!");
}
m_builder.setContentText(s);
m_notificationManager.notify(1, m_builder.build());
}
public static void vibrate(long[] pattern,boolean isRepeat) {
if(m_vibrator == null){
m_vibrator = (Vibrator) m_instance.getSystemService(Context.VIBRATOR_SERVICE);
}
m_vibrator.vibrate(pattern, isRepeat ? 1 : -1);
}
public static void vibrate(boolean isRepeat) {
if(m_vibrator == null){
m_vibrator = (Vibrator) m_instance.getSystemService(Context.VIBRATOR_SERVICE);
}
m_vibrator.vibrate(new long[]{100,10,100,100},isRepeat ? 1 : -1);
}
}
还要在Manifest.xml中添加权限相关的许可:
点击(此处)折叠或打开
-
<uses-permission android:name="android.permission.INTERNET"/>
-
<uses-permission android:name="android.permission.VIBRATE"/>
-
<uses-permission android:name="android.permission.WAKE_LOCK"/>
-
<uses-permission android:name="android.permission.DEVICE_POWER"/>
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
以下是C++函数调用上面Java方法的例子,主要就是一个QAndroidJniObject::callStaticMethod,注意其“描述Java方法参数与返回值”的格式(signature)。是因为高级语言的函数重载特性,导致只有函数名是无法确定调用哪个函数的。具体意义参考其他文档,很容易查到。
点击(此处)折叠或打开
-
void NotificationClient::sltUpdateAndroidNotification()
{
QAndroidJniObject javaNotification = QAndroidJniObject::fromString(m_notification);
QAndroidJniObject::callStaticMethod<void>("org/qtproject/example/notification/NotificationClient",
"notify",
"(Ljava/lang/String;)V",
javaNotification.object<jstring>());
}
void NotificationClient::sltVibrate(){
QAndroidJniObject::callStaticMethod<void>("org/qtproject/example/notification/NotificationClient",
"vibrate",
"(Z)V",
false);
}
void NotificationClient::sltWakeLockAcquire(){
QAndroidJniObject::callStaticMethod<void>("org/qtproject/example/notification/NotificationClient",
"wakeLockAcquire",
"()V");
}
void NotificationClient::sltWakeLockRelease(){
QAndroidJniObject::callStaticMethod<void>("org/qtproject/example/notification/NotificationClient",
"wakeLockRelease",
"()V");
}
三、最后提一下WakeLock
没有开启WakeLock的定时程序,当屏幕关闭后,没法正常工作。因为Android为了省电,系统认为“没有紧要任务”时会将CPU休眠,而且不打招呼。所以,需要后台运行任务时,要告诉系统维持CPU正常运转(参看上面的Java片段)。只是要注意,CPU的高频状态是个耗电大户,故而一旦不再需要了务必要把WakeLock释放掉。
最后,还缺什么呢?答:(1)C++和Java之间如何大量数据传输(2)与其他Android应用交换数据。以后再说吧,困了。