Qtandroid detailed (5): JNI calls Android system features (2)

Source: Internet
Author: User

In "Qtandroid detailed (4): JNI calls Android system features (1)" We give some simple examples of how to use the Qt JNI class library to access network status, System resource directory, current application information and so on, this time, we provide some new examples, These examples may be more practical. Examples of this article include:

    • Vibration
    • Keep the screen solid
    • Dynamically change the display direction of the app (horizontal, vertical)
    • Adjust screen brightness
    • Set ringtone mode

Example Introduction


Figure 1

We follow the order of the interface, one by one to see how these functions are implemented.

SOURCE Analysis

The code to build the interface is in the constructor of the Widget class, not to mention it. This time we change a pointers, do not list all the code, a function of a function to separate the code, so the article looks shorter.

Vibration

When you click on the "Vibrate" button in Figure 1, the onvibrate () slot is called, and its code is as follows:

void Widget::onvibrate () {    qandroidjnienvironment env;    Qandroidjniobject activity = androidactivity ();    Qandroidjniobject name = Qandroidjniobject::getstaticobjectfield (                "Android/content/context",                "VIBRATOR_ SERVICE ",                " ljava/lang/string; "                );    Check_exception ();    Qandroidjniobject Vibrateservice = Activity.callobjectmethod (                "Getsystemservice",                "(ljava/lang/string;) Ljava/lang/object; ",                name.object<jstring> ());    Check_exception ();    Jlong duration =;    Vibrateservice.callmethod<void> ("Vibrate", "(J) V", duration);    Check_exception ();}

Does it look familiar to you? In fact, using Qandroidjniobject to call the Java class library, the code written out looks similar ... You turn Over "qtandroid detailed (3): StartActivity Android Camera function" and "qtandroid detailed (4): JNI calls Android system function (1)" The code will be more sure of this. In fact, it embodies the general usage of Qandroidjniobject.

Many of the system services in Android have a name that is defined in the Context class as static member variables. I've seen it before. The name of the vibrator is Context.vibrator_service, and the corresponding class is android.os.Vibrator. The vibrator method, "void vibrate (long ms)", can generate vibrations that are measured in milliseconds.

Our C + + code first obtains the service name from the Android.content.Context class using the Qandroidjniobject::getstaticobjectfield () method, and then invokes the Activity's The Getsystemservice method gets the vibrator instance, and finally calls the vibrator vibrate (long) method to generate the vibration.

Change the way your app is displayed on the screen

Qt Creator gives us the generated app for Android, the default does not set the Activity of the screenorientation, if your phone rotation, the app may also become a horizontal screen or vertical screen display. When we need to apply a fixed display in a certain direction, we need to modify the "android:screenorientation" property of the <activity> tag in Androidmanifest.xml. In fact, the Android.app.Activity class also provides a "void setrequestedorientation (int requestedorientation)" method that allows us to adjust an Activity by code Direction of display.

To put it simply: an android application, there may be multiple activity, each activity can have its own screen display direction, that is, the screen display direction, is the activity characteristics.

When you click on the "Screenorientation" button in Figure 1, it will be called to the slot onscreenorientation (), the code is as follows:

void Widget::onscreenorientation () {    qandroidjnienvironment env;    Qandroidjniobject activity = androidactivity ();    Jint Orient = activity.callmethod<jint> (                "getrequestedorientation"                );    Check_exception ();    if (orient = = 1)    {        Orient = 0;    }    else    {        Orient = 1;    }    Activity.callmethod<void> (                "setrequestedorientation",                "(I) V", Orient);    Check_exception ();}

The Androidactivity () method in the Qtandroid namespace returns the activity object used by the Qt app, and then calls the Setrequestorientation () method directly to change the screen orientation of the current activity.

Ringtone mode

Mobile phone ringing, generally have ordinary (bell), mute, vibration three modes, corresponding to the code, is through the Android.media.AudioManager class "void Setringermode (int ringermode)" To set the ringtone mode. Audiomanager's name is Audio_service.

Setringermode The shaping parameters, there are three values: Ringer_mode_normal, Ringer_mode_silent, Ringer_mode_vibrate. These are defined as static member variables in the Android.media.AudioManager class, which we can get through the Qandroidjniobject::getstaticfield method in C + + code, but I stole a lazy in the code, Directly with the numbers. About the macro that corresponds to ringtone mode:

#define Ringer_mode_normal  2#define ringer_mode_silent  0#define ringer_mode_vibrate 1

As shown in 1, ringtone mode is selected by a set of radio buttons (Qradiobutton). I use Qbuttongroup in my code to manage three radio buttons, and set the ID of each button to the ringtone mode it represents. So when the Qbuttongroup "buttonclicked (int id)" Trigger, our slot "void widget::onringermodeclicked (int mode)" is called, the parameters are directly ring mode, very convenient.

Let's take a look at this set of ringtone mode radio button initialization code:

void Widget::initringermode (Qvboxlayout *layout) {qandroidjnienvironment env;    Qandroidjniobject activity = androidactivity ();                Qandroidjniobject name = Qandroidjniobject::getstaticobjectfield ("Android/content/context",                "Audio_service", "ljava/lang/string;"    );    Check_exception (); Qandroidjniobject Audioservice = Activity.callobjectmethod ("Getsystemservice", "(Ljava/lang    /string;) ljava/lang/object; ", name.object<jstring> ());    Check_exception ();    int mode = audioservice.callmethod<jint> ("Getringermode", "() I");    Check_exception ();    Layout->addwidget (New Qlabel ("Ringer Mode:"));    Qhboxlayout *rowlayout = new Qhboxlayout ();    Layout->addlayout (rowlayout);    Rowlayout->addspacing (30);    M_ringermodegroup = new Qbuttongroup (this);    Qradiobutton *normal = new Qradiobutton ("normal"); M_ringermOdegroup->addbutton (normal, ringer_mode_normal);    Rowlayout->addwidget (normal);    Qradiobutton *silent = new Qradiobutton ("silent");    M_ringermodegroup->addbutton (silent, ringer_mode_silent);    Rowlayout->addwidget (silent);    Qradiobutton *vibrate = new Qradiobutton ("vibrate");    M_ringermodegroup->addbutton (vibrate, ringer_mode_vibrate);    Rowlayout->addwidget (vibrate);        Switch (mode) {case ringer_mode_normal:normal->setchecked (true);    Break        Case ringer_mode_silent:silent->setchecked (TRUE);    Break        Case ringer_mode_vibrate:vibrate->setchecked (TRUE);    Break } Connect (M_ringermodegroup, SIGNAL (buttonclicked (int)), this, SLOT (onringermodeclicked (int)));}

In the above code, I also called Android.media.AudioManager's "int Getringermode ()" method to get the system's current ringtone mode, and then select the corresponding radio button.

Below are the onringermodeclicked slots:

void widget::onringermodeclicked (int mode) {    qandroidjnienvironment env;    Qandroidjniobject activity = androidactivity ();    Qandroidjniobject name = Qandroidjniobject::getstaticobjectfield (                "Android/content/context",                "AUDIO_ SERVICE ",                " ljava/lang/string; "                );    Check_exception ();    Qandroidjniobject Audioservice = Activity.callobjectmethod (                "Getsystemservice",                "(ljava/lang/string;) Ljava/lang/object; ",                name.object<jstring> ());    Check_exception ();    Audioservice.callmethod<void> (                "Setringermode", "(I) V", mode                );    Check_exception ();}

The Code and Onvibrate () are no longer explained.

Keep your screen solid

Some applications, such as video, do not want the Android phone to hibernate or lock the screen at runtime, so you need to keep the screen lit.

There are two ways to make the screen light on Android, one in the Activity's OnCreate () method, by adding the following code before calling Setcontentview ():

GetWindow (). SetFlags (WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, WindowManager.LayoutParams.FLAG_KEEP_ SCREEN_ON);

No special permissions are required in this way. In Qt, however, we cannot use this approach through Qandroidjniobject. Because when our interface comes out, Setcontentview () has been called ... In addition, there is a thread problem. So I used the second way: PowerManager.

Android.os.PowerManager can control whether the screen is often lit and its service name is Context.power_service. The PowerManager method "WakeLock newwakelock (int flag, String tag)" Can obtain a WakeLock instance where flag can be one of the following:

    • Partial_wake_lock (constant value 1)
    • Screen_dim_wake_lock (constant value 6)
    • Screen_bright_wake_lock (constant value 10)
    • Full_wake_lock (constant value 16)

I use Screen_bright_wake_lock in the example, and the corresponding constant value is 10. I use constants directly, not using Qandroidjniobject::getstaticfield () to get this constant.

When the WakeLock instance is obtained, it can call its "void Acquire ()" method to complete the lock and call its "void release ()" method to release the lock. We should release the lock at the right time, otherwise it will be very power-hungry.

In Figure 1 I used a check box (Qcheckbox) to control whether the screen is always lit, the corresponding slot is onscreenonchecked, the code is as follows:

void widget::onscreenonchecked (bool checked) {Qandroidjnienvironment env;    Qandroidjniobject activity = androidactivity ();            if (m_lastchecked) {if (M_wakelock.isvalid ()) {m_wakelock.callmethod<void> ("release");        Check_exception ();        } m_lastchecked = false;    Return                } Qandroidjniobject name = Qandroidjniobject::getstaticobjectfield ("Android/content/context",                "Power_service", "ljava/lang/string;"    );    Check_exception (); Qandroidjniobject Powerservice = Activity.callobjectmethod ("Getsystemservice", "(Ljava/lang    /string;) ljava/lang/object; ", name.object<jstring> ());    Check_exception ();    Qandroidjniobject tag = qandroidjniobject::fromstring ("Qtjniwakelock"); M_wakelock = Powerservice.callobjectmethod ("Newwakelock", "(iljava/lang/string;) Landroid/os /powermanager$wakElock; ",//screen_bright_wake_lock tag.object<jstring> ());    Check_exception ();        if (M_wakelock.isvalid ()) {m_wakelock.callmethod<void> ("acquire");    Check_exception (); } m_lastchecked = true;}

One thing to note here is that WakeLock is the inner class of android.os.PowerManager, and when we access the inner class through JNI, the signature is the "Outer$inner" format, such as "Powermanager$wakelock".

I also added Wake_lock permissions to the app.

Adjust screen brightness

The screen brightness can be adjusted in the Android phone's settings interface, which is achieved by modifying the Settings. An app needs to request Write_settings permissions to adjust the Settings.

The Android.provider.Settings.System class provides the following two static methods:

    • Static Boolean Putint (Contentresolver, String key, int value);
    • static int getInt (Contentresolver, String key);

The Putint method is used to write a setting (Key-value pair), and getint is used to get the value represented by the key.

System is the inner class of the Settings class, which should be noted when JNI signatures are signed.

As shown in 1, I use a qslider to adjust the screen brightness, the screen brightness range is 0~255. When you drag Qslider, the slot onbrightnesschanged is triggered and the code is as follows:

void widget::onbrightnesschanged (int value) {qandroidjnienvironment env;    Qandroidjniobject activity = androidactivity (); Qandroidjniobject contentresolver = Activity.callobjectmethod ("Getcontentresolver", "() Land    Roid/content/contentresolver; ");    Check_exception ();    Set brightness mode to MANUAL qandroidjniobject Brightnesstag = qandroidjniobject::fromstring ("screen_brightness");    Qandroidjniobject Brightnessmodetag = qandroidjniobject::fromstring ("Screen_brightness_mode");                bool OK = qandroidjniobject::callstaticmethod<jboolean> ("Android/provider/settings$system", "Putint", "(Landroid/content/contentresolver; Ljava/lang/string;i) Z ", contentresolver.object<jobject> (), brightnessmodetag.object&lt    ;jstring> (), 0);    Check_exception (); Qdebug () << "Set brightness mode to MANUAL-" << OK;    Set brightness to value OK = qandroidjniobject::callstaticmethod<jboolean> ("Android/provide R/settings$system "," Putint "," (Landroid/content/contentresolver; Ljava/lang/string;i) Z ", contentresolver.object<jobject> (), brightnesstag.object<jst    Ring> (), value);    Check_exception (); Qdebug () << "set Brightness to" << value << "Result-" << OK;

You may notice that the first parameter of Putint and GetInt, the type is contentresolver, the fully qualified class name is Android.content.ContentResolver, the Activity method "Contentresolver Getcontentresolver () "Can get to the Contentresolver instance, which is how I get the Contentresolver instance at the beginning of the onbrightnesschanged slot.

Settings.system This class modifies various settings of the system, and it defines a number of static constants to identify the configuration items. Screen_brightness and Screen_brightness_mode are the two I used in the code to identify the screen brightness, which identifies the screen brightness mode. All of them are string constants, and I'm lazy, using the solid string in my Android document directly.

Some users may set the screen brightness mode to Automatic, in automatic mode, modify the System in the screen_brightness is not valid, so I initially rudely set the screen brightness mode to manual. The static constant screen_brightness_mode_automatic of the system class (a value of 1) represents the auto-tuning mode, and the Screen_brightness_mode_manual (value 0) represents the manual mode. I am lazy again, or directly use the value.


The way I use it will affect the global settings of Android ... It's not necessarily what you want, OH. If you only want to modify the screen brightness of the current app, there's another way: Set the properties of the Window for the Activity. The corresponding Java code is as follows:

      Windowmanager.layoutparams LP = Window.getattributes ();      lp.screenbrightness = brightness;      Window.setattributes (LP);

If you want to implement the above Java code through JNI in Qt, you may get an error because the code above must be called in the UI thread where the Android Activity resides, and the QT thread, and the activity's thread, are two different threads. For a detailed analysis, see theQt on Android core programmingThe 13th chapter of the "Qt on Android Secret".


------------

The amount of God, finally said it is finished. It doesn't look like you're talking about Qt C + + code, it's about the Android class library ... It is undeniable that the use of qandroidjniobject for JNI development is indeed Jiangzi.


Look Back:

    • Qtandroid detailed (4): JNI calls Android system features (1)
    • Qtandroid detailed (3): StartActivity Android camera function
    • Qtandroid (2): StartActivity and its little friends
    • Qtandroid detailed (1): Qandroidjniobject
    • Qt on Android column


Qtandroid detailed (5): JNI calls Android system features (2)

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.