Search code examples
androiddelphi

Delphi 10.3.3 , Android App AutoStart on Boot ( Android 8.x , 10.x )


I created a java file with following content :

package com.embarcadero.XLRBoot;
     
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.Context;
     
public class startup extends BroadcastReceiver
{
     
    @Override
        public void onReceive(Context context, Intent intent) 
        {
               Intent sintent = new Intent();
           sintent.setClassName(context, "com.embarcadero.firemonkey.FMXNativeActivity");
               sintent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
               context.startActivity(sintent);
        }
     
}

I have created a JAR file from this like this :

C:\Program Files (x86)\Java\jdk1.7.0_71\bin>jar cf com-embarcadero-XLRBoot.jar "d:\Delphi XE 10\XLR Spider\Boot Receiver\com-embarcadero-XLRBoot.java"

My AndroidManifest.template looks like this :

<?xml version="1.0" encoding="utf-8"?>
<!-- BEGIN_INCLUDE(manifest) -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="%package%"
        android:versionCode="%versionCode%"
        android:versionName="%versionName%"
        android:installLocation="%installLocation%">

    <uses-sdk android:minSdkVersion="%minSdkVersion%" android:targetSdkVersion="%targetSdkVersion%" />
    <%uses-permission%>
    <uses-feature android:glEsVersion="0x00020000" android:required="True"/>
    <application android:persistent="%persistent%" 
        android:restoreAnyVersion="%restoreAnyVersion%" 
        android:label="%label%" 
        android:debuggable="%debuggable%" 
        android:largeHeap="%largeHeap%"
        android:icon="%icon%"
        android:theme="%theme%"
        android:hardwareAccelerated="%hardwareAccelerated%"
        android:resizeableActivity="false">

        <%provider%>
        <%application-meta-data%>
        <%uses-libraries%>
        <%services%>
        <!-- Our activity is a subclass of the built-in NativeActivity framework class.
             This will take care of integrating with our NDK code. -->
        <activity android:name="com.embarcadero.firemonkey.FMXNativeActivity"
                android:label="%activityLabel%"
                android:configChanges="orientation|keyboard|keyboardHidden|screenSize"
                android:launchMode="singleTask">
            <!-- Tell NativeActivity the name of our .so -->
            <meta-data android:name="android.app.lib_name"
                android:value="%libNameValue%" />
            <intent-filter>  
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter> 
        </activity>
        <receiver android:name="com.embarcadero.firemonkey.notifications.FMXNotificationAlarm" />
        <receiver android:name="com.embarcadero.XLRBoot"
                android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </receiver>
        <!-- Registration is complete -->    
        <%activity%>
        <%receivers%>
    </application>
</manifest>
<!-- END_INCLUDE(manifest) -->

I have set following Permissions in Delphi : [x] Receive boot completed [x] Reorder tasks

I compile my App, Run it, stop it, reboot device. I get an error that it stopped.

In the logs I see following entry :

04-20 12:38:49.087  2769  2769 E AndroidRuntime: FATAL EXCEPTION: main
04-20 12:38:49.087  2769  2769 E AndroidRuntime: Process: com.embarcadero.XLRBoot, PID: 2769
04-20 12:38:49.087  2769  2769 E AndroidRuntime: java.lang.RuntimeException: Unable to instantiate receiver com.embarcadero.XLRBoot: java.lang.ClassNotFoundException: Didn't find class "com.embarcadero.XLRBoot" on path: DexPathList[[zip file "/data/app/com.embarcadero.XLRBoot-OHpYv4loPMPls2q6DuLOLA==/base.apk"],nativeLibraryDirectories=[/data/app/com.embarcadero.XLRBoot-OHpYv4loPMPls2q6DuLOLA==/lib/arm, /data/app/com.embarcadero.XLRBoot-OHpYv4loPMPls2q6DuLOLA==/base.apk!/lib/armeabi-v7a, /system/lib, /system/vendor/lib, /system/vendor/lib/hw]]
04-20 12:38:49.087  2769  2769 E AndroidRuntime:    at android.app.ActivityThread.handleReceiver(ActivityThread.java:3174)
04-20 12:38:49.087  2769  2769 E AndroidRuntime:    at android.app.ActivityThread.-wrap17(Unknown Source:0)
04-20 12:38:49.087  2769  2769 E AndroidRuntime:    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1675)
04-20 12:38:49.087  2769  2769 E AndroidRuntime:    at android.os.Handler.dispatchMessage(Handler.java:106)
04-20 12:38:49.087  2769  2769 E AndroidRuntime:    at android.os.Looper.loop(Looper.java:164)
04-20 12:38:49.087  2769  2769 E AndroidRuntime:    at android.app.ActivityThread.main(ActivityThread.java:6518)
04-20 12:38:49.087  2769  2769 E AndroidRuntime:    at java.lang.reflect.Method.invoke(Native Method)
04-20 12:38:49.087  2769  2769 E AndroidRuntime:    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
04-20 12:38:49.087  2769  2769 E AndroidRuntime:    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
04-20 12:38:49.087  2769  2769 E AndroidRuntime: Caused by: java.lang.ClassNotFoundException: Didn't find class "com.embarcadero.XLRBoot" on path: DexPathList[[zip file "/data/app/com.embarcadero.XLRBoot-OHpYv4loPMPls2q6DuLOLA==/base.apk"],nativeLibraryDirectories=[/data/app/com.embarcadero.XLRBoot-OHpYv4loPMPls2q6DuLOLA==/lib/arm, /data/app/com.embarcadero.XLRBoot-OHpYv4loPMPls2q6DuLOLA==/base.apk!/lib/armeabi-v7a, /system/lib, /system/vendor/lib, /system/vendor/lib/hw]]
04-20 12:38:49.087  2769  2769 E AndroidRuntime:    at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:125)
04-20 12:38:49.087  2769  2769 E AndroidRuntime:    at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
04-20 12:38:49.087  2769  2769 E AndroidRuntime:    at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
04-20 12:38:49.087  2769  2769 E AndroidRuntime:    at android.app.ActivityThread.handleReceiver(ActivityThread.java:3169)
04-20 12:38:49.087  2769  2769 E AndroidRuntime:    ... 8 more

I obviously missed something, but what ?

Thank you for the help.

Regards Robert

UPDATE 4

I removed the previous updates because I was a bit off . So this is how it seems like I need to properly create the files.

Generate Class File

javac -Xlint:all -classpath "c:\Users\Public\Documents\Embarcadero\Studio\20.0\PlatformSDKs\android-sdk-windows\platforms\android-26\android.jar" "d:\Delphi XE 10\XLR Spider\Boot Receiver\0.2\startup\com\embarcadero\XLRBoot\startup.java" -d "d:\Delphi XE 10\XLR Spider\Boot Receiver\0.2\startup"

Generate JAR file :

jar cf "d:\Delphi XE 10\XLR Spider\Boot Receiver\0.2\startup\com\embarcadero\XLRBoot\startup.jar" -C "d:\Delphi XE 10\XLR Spider\Boot Receiver\0.2\startup\com\embarcadero\XLRBoot" startup.class

Delphi gives a EXEC(1) Exec Error.


Solution

  • Step 1 :

    create src\com\XLR folder in your App Directory

    there create the file BootReceiver.java with the following content :

    package com.XLR;
    
    import android.app.Activity;
    import android.content.BroadcastReceiver;
    import android.content.Intent;
    import android.content.Context;
    
    public class BootReceiver extends BroadcastReceiver
    {
    
            @Override
            public void onReceive(Context context, Intent intent) 
            {
               Intent launchintent = new Intent();
               launchintent.setClassName(context, "com.embarcadero.firemonkey.FMXNativeActivity");           
               launchintent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
               context.startActivity(launchintent);  
            }
    
    }
    

    Step 2 :

    Under your App Directory create build.bat with following content :

    @echo off
    echo.
    echo Compiles your Java code into classes.dex
    echo Verified to work in Delphi 10.3.3
    echo.
    echo Place this batch in a java folder below your project (project\java)
    echo Place the source in project\java\src\com\dannywind\delphi
    echo If your source file location or name is different, please modify it below.
    echo.
    
    setlocal
    
    set ANDROID_JAR="C:\Users\Public\Documents\Embarcadero\Studio\20.0\PlatformSDKs\android-sdk-windows\platforms\android-26\android.jar"
    set DX_LIB="C:\Users\Public\Documents\Embarcadero\Studio\20.0\PlatformSDKs\android-sdk-windows\build-tools\28.0.2\lib"
    set EMBO_DEX="D:\PRG\20.0\lib\android\debug\classes.dex"
    set PROJ_DIR=%CD%
    set VERBOSE=0
    set JAVASDK="C:\Program Files (x86)\Java\jdk1.7.0_71\bin"
    set DX_BAT="C:\Users\Public\Documents\Embarcadero\Studio\20.0\PlatformSDKs\android-sdk-windows\build-tools\28.0.2\dx.bat"
    
    echo.
    echo Compiling the Java source files
    echo.
    pause
    mkdir output 2> nul
    mkdir output\classes 2> nul
    if x%VERBOSE% == x1 SET VERBOSE_FLAG=-verbose
    %JAVASDK%\javac %VERBOSE_FLAG% -Xlint:all -classpath %ANDROID_JAR% -d output\classes -source 1.6 -target 1.6 src\com\XLR\BootReceiver.java
    
    echo.
    echo Creating jar containing the new classes
    echo.
    pause
    mkdir output\jar 2> nul
    if x%VERBOSE% == x1 SET VERBOSE_FLAG=v
    %JAVASDK%\jar c%VERBOSE_FLAG%f output\jar\XLRBoot.jar -C output\classes com
    
    
    :Exit
    
    endlocal
    

    Step 3 :

    now run build.bat and it will create the class and jar files in the Output Directory in your App Directory.

    Step 4 :

    Alter your AndroidManifest.template like this

    <?xml version="1.0" encoding="utf-8"?>
    <!-- BEGIN_INCLUDE(manifest) -->
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
            package="%package%"
            android:versionCode="%versionCode%"
            android:versionName="%versionName%"
            android:installLocation="%installLocation%">
    
        <uses-sdk android:minSdkVersion="%minSdkVersion%" android:targetSdkVersion="%targetSdkVersion%" />
        <%uses-permission%>
        <uses-feature android:glEsVersion="0x00020000" android:required="True"/>
        <application android:persistent="%persistent%" 
            android:restoreAnyVersion="%restoreAnyVersion%" 
            android:label="%label%" 
            android:debuggable="%debuggable%" 
            android:largeHeap="%largeHeap%"
            android:icon="%icon%"
            android:theme="%theme%"
            android:hardwareAccelerated="%hardwareAccelerated%"
            android:resizeableActivity="false">
    
            <%provider%>
            <%application-meta-data%>
            <%uses-libraries%>
            <%services%>
            <!-- Our activity is a subclass of the built-in NativeActivity framework class.
                 This will take care of integrating with our NDK code. -->
            <activity android:name="com.embarcadero.firemonkey.FMXNativeActivity"
                    android:label="%activityLabel%"
                    android:configChanges="orientation|keyboard|keyboardHidden|screenSize"
                    android:launchMode="singleTask">
                <!-- Tell NativeActivity the name of our .so -->
                <meta-data android:name="android.app.lib_name"
                    android:value="%libNameValue%" />
                <intent-filter>  
                    <action android:name="android.intent.action.MAIN" />
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter> 
            </activity>
            <receiver android:name="com.embarcadero.firemonkey.notifications.FMXNotificationAlarm" />
            <receiver android:name="com.XLR.BootReceiver"
                    android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
                <intent-filter>
                    <action android:name="android.intent.action.BOOT_COMPLETED" />
                    <category android:name="android.intent.category.DEFAULT" />
                </intent-filter>
            </receiver>
            <!-- Registration is complete -->    
            <%activity%>
            <%receivers%>
        </application>
    </manifest>
    <!-- END_INCLUDE(manifest) -->
    

    Step 5:

    Add the output\jar\XLRBoot.jar file to your Libraries inside Delphi and Run the programm.

    Step 6:

    After Run the Program Starts, Stop it Start it again . Now Reboot it will start. Turn Device Off and Turn On again and it will start.

    Thank you.

    SPECIAL NOTE FOR ANDROID 10 :

    You must set the Permissions System Alert window in Delphi. And on the Phone under App Info -> Advanced enable the Display over other apps settings.