<li>Always before include QtAndroidTools/QtAndroidTools.pri add the define labels for specify the library tools you want to include/exclude from your project compilation:<br/>
<p>Help in manage the apk expansion files download</p>
<p>Apk upload size limit is currently 100MB but in case your app require more data the Android Console allow to "attach" two files connected to your app. Official documentation about this feature is <ahref="https://developer.android.com/google/play/expansion-files"target="_blank">here</a>, is <u>strongly suggested</u> to read it for allow a better comprension about how to use this tool. Usually the expansion files are downloaded by the Google Play together with the main app but in case the user delete it or some other problem occurs and the file will not be available anymore the app have to download again usually at startup. In this phase is required the java code of the two libraries explained in the documentation, the <i>Google Play Licensing Library</i> and the <i>Google Play APK Expansion Library</i>. However, at the time this post was written, there are a couple of problems. The official documentation suggest to get these libraries through the Android SDK Manager and then create two modules using the libraries just obtained. The problem here is the code of there libraries is very very old and use some deprecated dependencies making difficult the compilation using Qt Creator. It exist an updated version of these two libraries always developed by Google <ahref="https://github.com/google/play-apk-expansion"target="_blank">here</a> and <ahref="https://github.com/google/play-licensing"target="_blank">here</a>. However also these two latest libraries are not supported by a long time and doesn't work very well in the latest versions of Android, from 8 and above. For this reasons this tool implement the two updated version community supported <ahref="https://github.com/bolein/better-apk-expansion"target="_blank">better-apk-expansion</a> and <ahref="https://github.com/bolein/better-licensing"target="_blank">better-licensing</a> that make the same job but are updated enough for support the new notify feature of Android 8. I only made a small modify for support the Qt multi language engine. In the version inside the tool the java library ask to the C++ level for the info text to use in the Android notify label allowing the Qt language selector to select the correct language string.</p>
<p>Remember for have the download library working as expected you have to set the following permission in your app:</p>
<p>Also note, in case your Android app is target for version 23 or above you have to explicitly ask for the <i>WRITE_EXTERNAL_STORAGE</i> permission cause this is one of the "dangerous" permission. You can use the other <ahref="#AppPermissions">AppPermissions</a> tool available in this library. Also you have to correctly the various part of the library by addicting these lines inside your <i>AndroidManifest.xml</i> file:</p>
<p><u>Please note from now it's assumed you have read the documentation</u> and already know the type and the format of expansion files is possible to upload and how the licensing engine work. First initialization is the following:</p>
<p>The <i>base64PublicKey</i> can be found in the Android Console app info and the <i>salt</i> is a random array of 20 bytes you have to generate by yourself. This is required for encrypt your data stored of the server. <i>Version</i> and <i>size</i> is required for identify your main and patch file. You can upload only the main file (and then you have to set only the <i>main</i> fields), these info are used to check if the current expansion files eventually already present in the device correspond in term of version number and file size.</p>
<p>Once configured the basic info you can check the operation to make by calling the following function:</p>
<p>mean your expansion file are already available in the device than there is nothing to do, you can proceed with the app execution. In case of return:</p>
<p>mean the apk expansion files download is started than you have to manage the download progress info. A download notify will be showed in the system status bar but your app should also show a progress control to inform the user regarding the operation in progress and that he have to wait. All other return codes are basically error conditions, check the library sources to see all the possible error types.</p>
<imgsrc="images/apkexpansionfiles1.png">
<p>During download phase the tool generate two signals updating you about current status as follow:</p>
<p><i>onDownloadStateChanged</i> have the <i>newState</i> param informing about the download state changed. Check the sources for all the possible values. <i>onDownloadProgress</i> report info about the download process like current size and time left. Once download completed or if your expansion files are already available is possible to retrieve the full path of both files by use the following functions:</p>
<p>A specific note regarding the function <i>getString()</i>. It return an info string connected with the current download status and some other info. It's used internally to pass correct language string to the java library but you can use also for the main interface as in demo example.</p>
</div>
<divclass="section-txt"id="AppPermissions">
<h3>AppPermissions</h3>
<p>This tool allow to request Android app permissions in an easier way.</p>
<p>From Android version 23 (Marshmallow) there are a list of special permission called "dangerous" because are directly connected to personal data of the user like calendar, contacts list and so on (official documentation <ahref="https://developer.android.com/guide/topics/permissions/overview"target="_blank">here</a>). If your app is target for this version and above and your manifest file contains one of the dangerous permissions you have to explicitly get the user authorization for have such permission granted. In the demo app four of these dangerous permission will be requested as follow:</p>
<imgsrc="images/apppermissions1.png">
<p>There are two functions for request permissions, one accept a list of permissions for allow a unique request for all and another can be used to ask for a single permission only. In this example the multiple request function will be used as follow:</p>
<preclass="prettyprint">import QtAndroidTools 1.0
...
readonly property var permissionsNameList: ["android.permission.WRITE_EXTERNAL_STORAGE","android.permission.READ_CALENDAR","android.permission.READ_PHONE_STATE","android.permission.READ_CONTACTS"]
<p>The call of this function will have a result to show the system message informing the user the app require the specific permissions and ask for approval:</p>
<p>Each item in the list contain the param <i>name</i> containing the permission string name and the boolean field <i>granted</i> informing if the user allowed the app to get the permission or not. Please note, if you app will be target under version 23 this signal will be emitted immediately without show any messagebox and, obviously, with all the permission automatically granted. This for allow the code working in the same way independently by the Android target version selected. In case the user don't granted a permission this special call is used in the code:</p>
<p>This function is quite particular and return true only in the case a first attempt to ask to permission has been denied. Basically it "suggest" to show a message to the user explaining why your app need the specific permission before retry to ask for permission again:</p>
<imgsrc="images/apppermissions3.png">
<p>Once explained the reasons you can ask again for the same permission by using this time the single request function:</p>
<p>Now please note a very important particular. Theoretically you can ask for the same permission infinitely, however from the second time you ask for the same permission the system message window will appear as following:</p>
<imgsrc="images/apppermissions4.png">
<p>As you can note in this case there is a checkbox allowing the user to not be annoyed by your request anymore (<i>Don't ask again</i>). If the user will check it and will deny the request again any next request for the permission will be automatically denied without show any message than be careful in decide when ask for permission and, above all, to explain very clearly why you need that permission. After the second try the signal reporting the choice result will be generated again with the updated situation:</p>
<imgsrc="images/apppermissions5.png">
</div>
<divclass="section-txt"id="AdMobBanner">
<h3>AdMobBanner</h3>
<p>This tool allow to show AdMob banner inside QML app.</p>
<p>Official documentation about AdMob banner is <ahref="https://developers.google.com/admob/android/banner"target="_blank">here</a>, please <u>read before continue</u> for understand the options exported by the tool. Remember for allow banner to be loaded your app need the following permissions:</p>
<p>The <i>unitId</i> is the string generated when you create a new ad unit inside the AdMob site. It's used to identify the ad connected to your app. Using this id you can know how much you earn from this ad unit. The property <i>type</i> is the banner type you want to show. Possible values are:</p>
<preclass="prettyprint">TYPE_BANNER
TYPE_FULL_BANNER
TYPE_LARGE_BANNER
TYPE_MEDIUM_RECTANGLE
TYPE_SMART_BANNER
TYPE_WIDE_SKYSCRAPER</pre>
<p>This item generate the following signals informing regarding the ad status:</p>
<preclass="prettyprint">onLoadError
onLoading
onLoaded
onClosed
onClicked</pre>
<p>The only signal passing a param is onLoadError, called in case of problem in loading ad. The param is <i>errorId</i> and possible values are:</p>
<p>When you want to load and show the banner you have to call the <i>show()</i> function and for hide the <i>hide()</i> functions (banner is the id name of the item in the example above). Function <i>reload()</i> force reload of a new banner.</p>
<p>Please note the banner is a native android view over the QML window, that's mean will stay over anything painted into in and you can not place nothing over the banner.</p>
<imgsrc="images/admobbanner1.png">
</div>
<divclass="section-txt"id="AdMobInterstitial">
<h3>AdMobInterstitial</h3>
<p>This tool allow to show AdMob interstitial inside QML app.</p>
<p>Official documentation about AdMob interstitial is <ahref="https://developers.google.com/admob/android/interstitial"target="_blank">here</a>, please <u>read before continue</u> for understand the options exported by the tool. Remember for allow interstitial to be loaded your app need the following permissions:</p>
<p>The <i>unitId</i> is the string generated when you create a new ad unit inside the AdMob site. It's used to identify the ad connected to your app. Using this id you can know how much you earn from this ad unit.</p>
<p>This item generate the following signals informing regarding the ad status:</p>
<preclass="prettyprint">onLoadError
onLoading
onLoaded
onClosed
onClicked</pre>
<p>The only signal passing a param is onLoadError, called in case of problem in loading ad. The param is <i>errorId</i> and possible values are:</p>
<preclass="prettyprint">ERROR_INTERNAL
ERROR_NETWORK
ERROR_INVALID_REQUEST
ERROR_NO_FILL</pre>
<p>Item have two function as follow:</p>
<preclass="prettyprint">interstitial.load()
interstitial.show()</pre>
<p>The interstitial have to be loaded before show and since loading is not immediate you have to preload a bit in advance before the time to show. You can follow the loading status through the item signals. Once revecied the <i>onLoaded</i> signal this mean your new interstitial is ready to be showed.</p>
<p>This type of ad have a button allowing the user to close it than you just have to wait about the user choice. Remember also in this case the ad window will go over the QML window and you can not paint anithing on top of it.</p>
<p>This tool allow to show AdMob Rewarded Video inside QML app.</p>
<p><b>IMPORTANT NOTE:</b> The current implementation of Rewarded Video API have to be used with only a single instance of the tool cause only one video can be loaded at a time. However a new set of API allowing multiple video loaded at the same time is going to be released (currently are still in beta). This is the reasons current implementation of this tool allow multiple instances. When the new API set will be released this tool code will be updated and change will be totally transparent from application side.</p>
<p>Official documentation about AdMob Rewarded Video is <ahref="https://developers.google.com/admob/android/rewarded-video"target="_blank">here</a>, please <u>read before continue</u> for understand the options exported by the tool. Remember for allow video to be loaded your app need the following permissions:</p>
<p>The <i>unitId</i> is the string generated when you create a new ad unit inside the AdMob site. It's used to identify the ad connected to your app. Using this id you can know how much you earn from this ad unit.</p>
<p>This item generate the following signals informing regarding the ad status:</p>
<preclass="prettyprint">onRewarded
onLoadError
onLoading
onLoaded
onOpened
onClosed
onStarted
onCompleted
onLeftApplication</pre>
<p>The only two signals passing a param is onLoadError and onRewarded. The first is called in case of problem in loading ad. The param is <i>errorId</i> and possible values are:</p>
<preclass="prettyprint">ERROR_INTERNAL
ERROR_NETWORK
ERROR_INVALID_REQUEST
ERROR_NO_FILL</pre>
<p>The record is called for inform about the rewarded values. It have two params, <i>type</i> and <i>amount</i>. Check the official documentation for know the value meaning.
<p>Item have two function as follow:</p>
<preclass="prettyprint">rewardedVideo.load()
rewardedVideo.show()</pre>
<p>The video have to be loaded before show and since loading is not immediate you have to preload a bit in advance before the time to show. You can follow the loading status through the item signals. Once revecied the <i>onLoaded</i> signal this mean your new video is ready to be played.</p>
<imgsrc="images/rewardedvideo1.png">
<p>This type of ad have a button allowing the user to close it than you just have to wait about the user choice. Remember also in this case the ad window will go over the QML window and you can not paint anithing on top of it.</p>
<imgsrc="images/rewardedvideo2.png">
<p>After the user close the video you'll receive the rewarded info.</p>
<p>This tool allow to retrieve the device albums and images</p>
<p>There are only the following functions, the first return the list of device albums and the second return the list of all images inside the album (full absolute path of each image):</p>
<preclass="prettyprint">import QtAndroidTools 1.0
QtAndroidImages.getAlbumsList()
QtAndroidImages.getAlbumImagesList(albumId)</pre>
<p>In particular the first function return an array of structures with the following two properties:</p>
<preclass="prettyprint">album.id
album.name</pre>
<p>As is possible easily undertand the first id the <i>id</i> of the album (to use as param for the second function) and the second is the <i>name</i> of the album as saved in the Android device.</p>
<p>This tool will show Android system notifications.</p>
<p>As usual for better understand how to use notification is strongly reccomended to read the official documentation <ahref="https://developer.android.com/guide/topics/ui/notifiers/notifications"target="_blank">here</a>.</p>
<p>The tool <i>QtAndroidNotification</i> allow to compose and show a system notification in a very easy way as follow:</p>
<preclass="prettyprint">QtAndroidNotification {
id: notification
title: "Notification title"
text: "This is the notification content"
expandableText: "This is a very very very very very very very very very very long expandable content"
channelName: "Notification channel"
smallIconName: "notification_icon_name"
largeIconSource: ":/images/logo.jpg"
}</pre>
<p>Available notification properties are the the following:</p>
<ul>
<li><i>title</i> : title of the notification.</li>
<li><i>text</i> : main content of the notification. This filed is mandatory and is limited to one line size.</li>
<li><i>expandableText</i> : in case you need to show a text longer than a line you can set this property with your full text. Based to the Android version the result will be a little different but, in any case, this part will be showed in addition of the text content.</li>
<li><i>channelName</i> : in Android 8.0 and above notification have to be associated to a channel, this for allow user to disable notifications associated to the specific channel. This is a mandatory value.</li>
<li><i>smallIconName</i> : another mandatory value. Basically this is the special format icon showed on system bar connected to the notification. You can find many tools allow to make this icon in the right format. Unfortunately, for support old Android verion, is not possible to pass this icon from Qt resource or from a image file on storage but have to be mandatorily use the apk drawable folders. For try to simplify you don't need to get the full app path but you simply can insert the name of the icon file (without extension) you set into drawable folder (check the demo source).</li>
<li><i>largeIconSource</i> : large icon you can show into notification. You can use an image from Qt resource system of from a file.</li>
<p>In case you need to show a progress bar in the notification there are available the following additional properties:</p>
<ul>
<li><i>progressBar.max</i> : the max value of the progress bar.</li>
<li><i>progressBar.current</i> : The current value of the progress bar between zero and the max value.</li>
<li><i>progressBar.indeterminate</i> : boolean value for set the prograss bar in the indeterminate state. The result is an indicator that has the same style as the progress bar above, except the progress bar is a continuous animation that does not indicate completion.</li>
</ul>
<p>The progress bar is showed if you set the max value with a value greater than zero. For hide the progress bar set zero to both max nad current properties value.</p>
<p>Once set all the required properties you can show the notification by calling the corresponding function. The notification can be read and cleared directly by the user you can remove from app by using the <i>cancel()</i> call.</p>
<p>Explanation about fields above can be found in the official Android documentation <ahref="https://developer.android.com/reference/android/content/pm/PackageInfo"target="_blank">here</a>. The tool export only the most important info but if you need to have some additional data you can easily add you code by using JNI interface as showed in the sources.</p>
<imgsrc="images/apkinfo1.png">
</div>
<divclass="section-txt"id="BatteryState">
<h3>BatteryState</h3>
<p>This allow monitoring the battery level and state.</p>
<p>This tool install a listener for monitor the battery level and on charge state. There is nothing difficult in use since there are only two properties as follow:</p>
<preclass="prettyprint">import QtAndroidTools 1.0
QtAndroidBatteryState.level
QtAndroidBatteryState.onCharge</pre>
<p>Both properties support QML value binding than you can assign to a control for show always the updated value as in the demo example.</p>
<p>This tool allow to monitoring the strength of the phone signal.</p>
<p>This tool install a listener for monitor the phone signal. Remember for allow the library to work in this case the app need to have the following permission:</p>
<p>There are two properties reporting the strength of the phone signal in row number and based to the conventional states as follow:</p>
<preclass="prettyprint">import QtAndroidTools 1.0
QtAndroidSignalStrength.signalStrength
QtAndroidSignalStrength.signalLevel</pre>
<p>Signal level possible states are the following:</p>
<ul>
<li>LEVEL_GREAT</li>
<li>LEVEL_GOOD</li>
<li>LEVEL_MODERATE</li>
<li>LEVEL_POOR</li>
<li>LEVEL_NONE</li>
</ul>
<p><b>PLEASE NOTE:</b> the report the the signal strength change doesn't arrive immediately but, instead, require some seconds to be updated after the change. Don't worry if you don't see an immediate update, just wait a little.</p>