//Targeting Android 8 and higher

Targeting Android 8 and higher

From August 2018, all new apps on Google Play must target Android 8 (API level 26) or higher, and from November 2018, all app updates on Google Play must do the same. If your app also needs to request “dangerous” permissions, this article will help you achieve that.

Note: The demo in this article was devised with Delphi Tokyo 10.2.3, however it may work with earlier versions.

UPDATE: Brian Long has alerted me to the fact that using this solution, the status bar just appears as a white rectangle (i.e. no icons, time etc), something I should have noticed in my testing (too focused on problem at hand!). I’ll be looking into how to resolve this.

UPDATE 2: The files have now been updated to include an interim solution for the status bar problem. This includes:

MainFrm.pas
DW.SystemHelper.pas
DW.SystemHelper.Android.pas
dw-nativeactivity.jar

The interim solution involves setting the status bar translucent, which results in the total screen space for the app to include the status bar area, so there is now a rectangle at the top of the main form to account for this.

UPDATE 3: I’ve created another article that presents an alternative solution to “overriding” the activity, includes a workaround for an issue with TTakePhotoFromCameraAction, and an alternative solution for the status bar issue.

Up until now, by default, Delphi targets Android 4.0 (API level 14, otherwise known as Icecream Sandwich). The value (14) is inserted as the targetSdkVersion value in the AndroidManifest.xml file which is deployed with your app.

What does this mean for your apps? According to the documentation, this value tells the system it should not enable any compatibility behaviours to maintain your app’s forward-compatibility with the target version. If your app is set to target a particular API level, all features at that level that you use should be thoroughly tested to ensure your application works.

With the requirement for new apps to have the target API level of 26, there is at least one feature that is yet to be catered for in Delphi apps. In Android 6 (API level 23), requirements were introduced regarding application users privacy; namely that some resources are now designated “dangerous”, and applications will need to explicitly request permission to access to these resources at runtime, as well as having the permissions listed in the manifest.

In order to handle requests for permissions correctly, the application should call the requestPermissions method (of the Activity class), and the activity must override the onRequestPermissionsResult method of the Activity class in order to determine whether the user granted or denied access. Unfortunately at present, this method is not implemented by the FMXNativeActivity class (part of the FMX Java runtime), so unless you’re keen on modifying the FMX Java source and recompiling it, a little bit of “hacking” is required.

Fortunately, I (with the invaluable assistance of Brian Long) have done the work for you. Rather than go into an in-depth discussion of how the solution was devised, I’ll field questions in the comments. I will however describe how the demo is put together, which should guide you in how you can integrate it into your own apps.

First, you will need to download the Android SDK for API level 26 (i.e. Android 8). Run SDKManager located in the Android SDK folder, which by default appears in the directory as per the following image. Select at least the Android 8 SDK Platform and click Install:

Use the SDK Manager to change the illustrated SDK settings to API 26 (in my case 26.0.2):

Once you have created your project, the manifest template needs to be modified to replace the FMXNativeActivity with a class that descends from that class, but implements onRequestPermissionsResult. The following shows the part that needs to be changed:

NOTE: A side-effect of replacing the activity is that when debugging via the IDE, when the IDE says “Launching”, you will need to start the application manually on the device. 

Next, the application needs to have the .jar file that contains the replacement activity added to the Android Libraries node, which is under the Android target in the Project Manager:

The file (dw-nativeactivity.jar) is in the Lib folder of the KastriFree project.

I’ve devised a class called TSystemHelper, which follows a similar pattern to other classes I’ve constructed to implement functionality in a cross-platform manner. In the main form of the demo, I create an instance of TSystemHelper, assign the OnPermissionsResult event to a handler, and call the RequestPermissions method for various permissions that are classified as “dangerous”, such as Camera, Location and SMS.

The permission request results are passed back in a dynamic array of records (of type TPermissionsResults). The type has a  helper class that adds convenience methods such as AreAllGranted, which indicates whether all permissions in the request were granted. In my tests on my Android 8 device, I was expecting the user to be able to choose which permissions to grant or deny, however it just prompted me with a single query. Perhaps this is different (or will be) on other versions of Android, so I’ve left the code as it is.

You can find the code for the demo in the KastriFree project (the demo relies on units contained in the project).

By | 2018-07-03T07:54:59+00:00 May 17, 2018 11:22 pm|Uncategorized|14 Comments

About the Author:

14 Comments

  1. Stiaan Pretorius May 18, 2018 at 3:38 pm - Reply

    Hi

    With what versions of the SDK and NDK did you compile? What does your SDK settings look like?

    Regards
    Stiaan

    • Dave May 18, 2018 at 4:25 pm - Reply

      I’d forgotten that (a while ago) I had changed to the API level 26 SDK, so if you’re having trouble, I’m assuming that’s the reason why. I’ve updated the article to reflect this. I’m using the “default” NDK which is r9c.

  2. Armando Correa May 20, 2018 at 9:22 pm - Reply

    Hello you were able to solve the problem of the notification bar in white. It’s happening to me, too.

    • Dave May 29, 2018 at 9:21 am - Reply

      I’ve updated the article as well as some files.

  3. Lúcio Coelho May 30, 2018 at 8:12 am - Reply

    Boa tarde… não consigo encontrar em baixar o arquivo mensionado no post: O arquivo (dw-activity.jar) está na pasta Lib do projeto KastriFree.

    • Dave May 30, 2018 at 8:21 am - Reply

      O arquivo é chamado dw-nativeactivity.jar

  4. Fabricio Marques June 1, 2018 at 11:27 pm - Reply

    Hello! First of all thanks for the contribution of the solution, I have not yet been able to test it but I can not wait to try it … I was giving a researched and I saw a discourse about api26 in delphi, it even cites its solution, and from what I understood due to the Android 8 have more backgroud services the push notifications are not working properly. I would like to know if there is any possible solution and if there is any news of the position of the jetty regarding api26.

    topic link: https://stackoverflow.com/questions/50549970/delphi-new-apps-on-google-play-must-target-android-8-api-level-26-push-not

    I’m sorry for my English, I’m getting help from a translator.

    • Dave June 2, 2018 at 2:00 pm - Reply

      Eu pretendo olhar para o problema de notificações push e atualizar o artigo que eu postei há algum tempo.

      (I plan to look into the push notifications problem, and update the article I posted a while ago.)

    • Fernando Celio Leal July 19, 2018 at 4:43 am - Reply

      I have the same problem. On Android 6 it works perfectly, however on Android 8 the push notification does not work in the background

  5. sam mikael June 4, 2018 at 9:04 pm - Reply

    does embarcadero care about this change?

    • Dave June 4, 2018 at 10:11 pm - Reply

      I expect they do care, since their users would not be able to deploy to the app store without using workarounds. As to when the official support might be implemented, I do not know

  6. alissonrodrigo June 8, 2018 at 11:32 pm - Reply

    First of all thank you very much for your articles and resources made available.
    I’ll start preparing for these changes in our app. Today for notifications I use a solution published by you (http://delphiworlds.com/2017/05/add-firebase-cloud-messaging-mobile-apps-part-1/) if I implement the changes for api 26 as notifications will continue to work? Do you have this information?
    Thank you again.

  7. Ederson July 11, 2018 at 12:57 am - Reply

    Hi

    I’m receiving this error when compile the demo

    [DCC Error] MainFrm.pas(58): E2003 Undeclared identifier: ‘StatusBarHeight’

    This code when I comment, works fine

    StatusBarRectangle.Height := FSystemHelper.StatusBarHeight;

Leave a Reply

Show Buttons
Hide Buttons