Home
| pfodApps/pfodDevices
| WebStringTemplates
| Java/J2EE
| Unix
| Torches
| Superannuation
| CRPS Treatment
|
| About
Us
|
![]() |
Android Programming |
How to fix Google's Edge-to-Edge mess in your app when upgrading to Android 15 (posted 7th July 2025)
Fix for Google 's License Check crash: Service
Intent must be explicit on Android V5 and higher (posted 3rd
May 2018)
java.lang.IllegalArgumentException: Service Intent
must be explicit: Intent {
act=com.android.vending.licensing.ILicensingService
pfodApp is a mature general purpose display and control and charting app for microprocessors, that has been in development for the last 15 years. First as a J2ME app and then from 2012 onwards as an Android app. pfodApp strives to maintain backward compatibility with older mobiles so you can use that old phone as a display and control for your micro-computer project. As well as the paid pfodApp, there are free design apps, pfodDesigner and pfodGUIdesigner, which let you build menus and GUI's on your mobile and then generate the necessary Arduino code. pfodApp can connect via WiFi, BLE, Classic Bluetooth and optionally SMS to your device.
As a mature app the only major changes now are those forced on it by Google in order to be available on the latest models. The latest such, un-necessary, change require by Google, is to handle mandatory Edge-to-Edge on Android 15 (API 35) and above. This note covers how to handle that requirement while still maintaining support back to Android 8 (API 26).
pfodApp uses LinearLayout for each screen with a toolbar and … menu at the top and control buttons (Save, Exit, Cancel) at the bottom. When run on Android 15 the cutout at the top covers the toolbar and the phone's navigation buttons at the bottom cover the applications buttons making the app unusable.
To overcome this problem, the following line two lines of code were added to each setupWindow(R.layout.....) that is called by each onCreate() method for to setup that screen.
public void setupWindow(int layoutResId, boolean setAcceptButton) { setContentView(layoutResId); View mainView = findViewById(R.id.linearLayout); // Get a reference to your view's main layout WindowViewSupport.addMarginListener(mainView); // other setup code here
The WindowViewSupport class is
public class WindowViewSupport { static void addMarginListener(View mainView) { if (mainView == null) { return; } if (SDK_INT < 35) { return; } WindowInsets windowInsets = mainView.getRootWindowInsets(); if (windowInsets != null) { setInserts(mainView); return; } // add listener to be called when view attached mainView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() { @Override public void onViewAttachedToWindow(View v) { WindowViewSupport.setInserts(v); } @Override public void onViewDetachedFromWindow(View v) { // Do stuff when view has been detached from window } }); } static void setInserts(View mainView) { if (mainView == null) { return; } if (SDK_INT < 35) { return; } WindowInsets windowInsets = mainView.getRootWindowInsets(); if (windowInsets == null) { return; } int inTop = windowInsets.getSystemWindowInsetTop(); int inBottom = windowInsets.getSystemWindowInsetBottom(); int inLeft = windowInsets.getSystemWindowInsetLeft(); int inRight = windowInsets.getSystemWindowInsetRight(); mainView.setPadding(inLeft, inTop, inRight, inBottom); }
Due the vagaries of how Android created screens, sometimes the layout has been 'attached' before addMarginListener gets called. In this case getRootWindowInsets() returns the necessary screen inserts. It it returns null then the layout has not been 'attached' yet and in that case a listener is added to fix up the padding once the layout is attached. The (SDK_INT < 35) skips all this stuff for pre-Android 15 phones so the app's appearance does not change on them.
“Antlr is a powerful parser generator for reading, processing, executing, or translating structured text or binary files.”
Unfortunately for Android programmers it uses as number of Java libraries that are not available on Android systems. (When you go to package the app, proguard complains about missing swing classes and others)
This web page contains a partial port of Antlr 4.2.2 release of ANTLR to Android. Only the Lexer part of the Antlr release has been ported. That was all I needed to write my parser for pfodApp. In pfodApp the lexer parses all the text formatting codes and call support methods to build up a SpannableStringBuilder with the specified formatting applied.
The ported Eclipse Android Antlr 4.2.2 Lexer library project is available here as a zip file.
This is what was done to port the Lexer portion of Antlr V4.2.2 to an Android library.
generated lexer java file from grammar and check that is was correct using standard runtime library
removed runtime library from project
added java files from antlr4 runtime source directory one at a time to resolve compile errors
removed all @NonNull and @Nullable references
commented out code that references javax etc mainly toString() and tree display methods
added implementations of Arrays.copyOf and binarySearch that Android does not provide to misc.Utils and fixed all references in files used.
Removed all references to System.out and System.err (TODO add in Android Log calls as needed)
removed unsupported @SuppressWarnings
removed unused imports
The entire atn and dfa runtime packages have been ported to Android API 7 (Android V2.1+)
In misc package, GraphicsSupport.java, JFileChooserConfirmOverwrite.java, LogManager.java and TestRig.java have been omitted.
In Utils, waitForClose and addWindowListener methods have been removed and copyOf and binarySearch methods added.
In tree package, packages gui, pattern and xpath and other classes not need for compile have been removed, as this is a lexer only project. This is were more work is needed for a 'complete' port.
In runtime package, ConsoleErrorListener.java was removed (TODO replace with Android Log error listener), String.isEmpty() was replaced with (String.length() == 0), in DiagnosticErrorListener.java, compileParseTreePattern methods where removed from Parser as not needed the pfodApp Lexer (TODO fix this), ParserInterpreter was removed needs ArrayDeque and Deque implementations (TODO fix this), in Recognizer, ConsoleErrorListener.INSTANCE was removed, in RuleContext, save() and inspect() and toStringTree() methods where removed and toString() was replaced with empty string return.
Result is the port to Android that is about 80% complete.
If you do any further porting please feed that back here so we can provide a more complete port.
This bug has been in Google's code since Nov 2014 and is not fixed yet (as of May 2018) https://issuetracker.google.com/issues/37008856
The symptom is an IllegalArgument exception when running on
Android V5 or higher and with the target sdk set at >20
Caused
by: java.lang.IllegalArgumentException: Service Intent must be
explicit: Intent {
act=com.android.vending.licensing.ILicensingService
There are comments on how to fix the problem code (https://stackoverflow.com/questions/44904890/android-app-licencing-fatal-exception-service-intent-must-be-explicit) but you still need to find a set of sources for the google library.jar and modify them.
The simplest fix is to set the targetSdk to 19 (or 20 not tested) and then every thing just works on all Android versions. However if you are using Android Studio that is not an option. In that case you can do the following.
The library.zip file here contains an eclipse project with the corrected sources for the licensing service.
Unzip it somewhere and Import -> Existing Android code
into workspace into eclipse and check it compiles.
The
eclipse module will be called library. If you are still using Eclipse
to build you app, remove the library.jar dependencies and add this
project instead.
For use in Android Studio (V3), use File->New->Import
Module,
Navigate to the eclipse module dir and select it. (I
renamed my Android Studio module 'play_library')
In the next
screen ADT Import Preferences, untick all the boxes, the click
Finish
In the build.gradle file I set minsdk == 7 and targetsdk == 22.
The settings in the AndroidManifest.xml are overridden by the
build.gradle settings.
Note: You need to set the minskd to at
least 4 to allow the use of the setPackage() bug fix statement.
Remove library.jar from dependencies and added play_library
module
I also needed to removed compile files('libs/library.jar')
from build.gradle
Remove the existing library.jar from the libs
dir and do a Clean Project and Rebuild Project.
Finally test your app on Android V5 or higher.
Note: If you set targetsdk to >22 then you will need to do a
lot of coding rework to handle user permissions. See
Everything
every Android Developer must know about new Android's Runtime
Permission for the details.
Contact Forward Computing and Control by
©Copyright 1996-2024 Forward Computing and Control Pty. Ltd.
ACN 003 669 994