Android app is crashing after java based plugin has been added?

Hello everybody,

I developped a plugin based on the awesome template from UE4 - Making a Android Plugin in 10 minutes - Isara Tech. in order to detect when my android device goes out from sleep mode. I integrated this plug-in into my UE4 project, compiled and packaged successfuly…

BUT when I run my application on android devices, it systematically crashes after splash screen exits… I am investigating and testing things for days now without finding any solution to this problem.

If someone has the skill or the knowledge to support me, I would be grateful and I can offer some french food gifts :slight_smile:

Here is my xml file, where java code is encapsulated:

 <?xml version="1.0" encoding="utf-8"?>
 <!--GearVR plugin additions-->
 <root xmlns:android="http://schemas.android.com/apk/res/android">
     <!-- init section is always evaluated once per architecture -->
     <trace enable="true"/>
     <init>
         <log text="AndroidAPITemplate init"/>        
     </init>
 
   <androidManifestUpdates>
     <addElements tag="application">
       
       <activity android:name="com.isaratech.androidapi.AndroidAPITemplateActivity"
           android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation"
           android:label="@string/app_name" />
           
     </addElements>
 
         
   </androidManifestUpdates>
 
   <!-- optional additions to proguard -->
   <proguardAdditions>
     <insert><![CDATA[
       -keepattributes Signature
       -dontskipnonpubliclibraryclassmembers
 
      -keepclassmembers class com.epicgames.ue4.GameActivity {
             public <methods>;
             public <fields>;
      }
     ]]></insert>
   </proguardAdditions>
 
   <resourceCopies>
     <!-- Copy the generated resource file to be packaged -->
   </resourceCopies>
 
   <AARImports>
   </AARImports>
   
   <!-- optional additions to the GameActivity imports in GameActivity.java -->
     <gameActivityImportAdditions>
       <insert>
       import java.util.HashSet;
       import java.util.Arrays;
       import android.text.TextUtils;
       import android.graphics.BitmapFactory;
       import android.os.Handler;
       import android.widget.Toast;
       import android.content.BroadcastReceiver;
       import android.app.Activity;
       import android.content.Context;
       import android.content.Intent;
       import android.content.IntentFilter;
       import android.os.Build;
       import android.os.Bundle;
       import android.os.PowerManager;
     </insert>
     </gameActivityImportAdditions>
     
 
     <!-- optional additions to the GameActivity class in GameActivity.java -->
     <gameActivityClassAdditions>
         <insert>
         <![CDATA[
     private Boolean WakeUpFlag = false;
     /**
          * returns Current value of the WakeUpFlag
          */
      public void AndroidThunkJava_AndroidAPI_GetWakeUpFlagValue(Boolean WakeUpFlag_b) {
     WakeUpFlag_b = WakeUpFlag;
     }
         ]]>
         </insert>
     </gameActivityClassAdditions>
     
     <!-- optional additions to GameActivity onCreate metadata reading in GameActivity.java -->
     <gameActivityReadMetadataAdditions>
     <insert>
 
   </insert>
     </gameActivityReadMetadataAdditions>
     
     <!-- optional additions to GameActivity onCreate in GameActivity.java -->
     <gameActivityOnCreateAdditions>
         <insert>
         <![CDATA[
     Context context = getApplicationContext();
         final PowerManager mPowermanager = (PowerManager) context.getSystemService((Context.POWER_SERVICE));
             IntentFilter filter = new IntentFilter();
             filter.addAction((Intent.ACTION_SCREEN_ON));
             context.registerReceiver(new BroadcastReceiver() {
             @Override
             public void onReceive(Context context, Intent intent) {
                 WakeUpFlag = mPowermanager.isInteractive();
             }
         },filter);
         ]]>
         </insert>
     </gameActivityOnCreateAdditions>
 
     <!-- optional additions to GameActivity onDestroy in GameActivity.java -->
     <gameActivityOnDestroyAdditions>
         <insert>
         
         </insert>
     </gameActivityOnDestroyAdditions>
     
     
     <!-- optional additions to GameActivity onStart in GameActivity.java -->
     <gameActivityOnStartAdditions>
         <insert>
         
         </insert>
     </gameActivityOnStartAdditions>
 
     <!-- optional additions to GameActivity onStop in GameActivity.java -->
     <gameActivityOnStopAdditions>
         <insert>
         
         </insert>
     </gameActivityOnStopAdditions>
     
 
     <!-- optional additions to GameActivity onPause in GameActivity.java    -->
     <gameActivityOnPauseAdditions>
     <insert>
     <![CDATA[
     ]]>
     </insert>
   </gameActivityOnPauseAdditions>
 
 
   <!-- optional additions to GameActivity onResume in GameActivity.java    -->
   <gameActivityOnResumeAdditions>
     <insert>
     </insert>
   </gameActivityOnResumeAdditions>
 
 
     <!-- optional additions to GameActivity onActivityResult in GameActivity.java -->
     <gameActivityOnActivityResultAdditions>
         <insert>
         </insert>
     </gameActivityOnActivityResultAdditions>
     
 
     <!-- optional libraries to load in GameActivity.java before libUE4.so -->
     <soLoadLibrary>
         <!-- need this if plugin enabled and supported architecture, even if not packaged for GearVR -->
     </soLoadLibrary>
 </root>

Here is my cpp plugin code:

 #include "AndroidAPITemplatePrivatePCH.h"
 
 #if PLATFORM_ANDROID
 
 #include "Android/AndroidJNI.h"
 #include "AndroidApplication.h"
 
 #define INIT_JAVA_METHOD(name, signature) \
 if (JNIEnv* Env = FAndroidApplication::GetJavaEnv(true)) { \
     name = FJavaWrapper::FindMethod(Env, FJavaWrapper::GameActivityClassID, #name, signature, false); \
     check(name != NULL); \
 } else { \
     check(0); \
 }
 
 #define DECLARE_JAVA_METHOD(name) \
 static jmethodID name = NULL;
 
 DECLARE_JAVA_METHOD(AndroidThunkJava_AndroidAPI_ShowToast);        // Here goes the name of the method in the Java side
 DECLARE_JAVA_METHOD(AndroidThunkJava_AndroidAPI_GetWakeUpFlagValue);
 
 void UAndroidAPITemplateFunctions::InitJavaFunctions()
 {
     // Same here, but we add the Java signature (the type of the parameters is between the parameters, and the return type is added at the end,
     // here the return type is V for "void")
     // More details here about Java signatures: http://www.rgagnon.com/javadetails/java-0286.html
     INIT_JAVA_METHOD(AndroidThunkJava_AndroidAPI_GetWakeUpFlagValue, "(Z)V ");
 }
 #undef DECLARE_JAVA_METHOD
 #undef INIT_JAVA_METHOD
 
 #endif
 
 bool UAndroidAPITemplateFunctions::AndroidAPITemplate_GetWakeUpFlagValue()
 {
 #if PLATFORM_ANDROID
     if (JNIEnv* Env = FAndroidApplication::GetJavaEnv(true))
     {
         jboolean Result = false;
         FJavaWrapper::CallVoidMethod(Env, FJavaWrapper::GameActivityThis, AndroidThunkJava_AndroidAPI_GetWakeUpFlagValue, Result);
 
         /*const bool ReturnResult_b = Result;
 
                 Env->DeleteLocalRef(Result);*/
 
         return Result;
     }
     else
     {
         UE_LOG(LogAndroid, Warning, TEXT("ERROR: Could not get Java ENV\n"));
 
         return false;
     }
 #else
     return false;
 #endif
 }

Here is my plugin header:

#pragma once
 
 #include "AndroidAPITemplateFunctions.generated.h"
 
 UCLASS(NotBlueprintable)
 class UAndroidAPITemplateFunctions : public UObject {
     GENERATED_BODY()
     
 public:
 
 #if PLATFORM_ANDROID
     static void InitJavaFunctions();
 #endif
 
  
 
     /**
      * Get the WakeUpFlag value
      */
     UFUNCTION(BlueprintCallable, BlueprintPure, meta = (Keywords = "AndroidAPI ", DisplayName = "Get Wake Up Flag Value"), Category = "AndroidAPI")
         static bool AndroidAPITemplate_GetWakeUpFlagValue();
 
 };

and finally the build.cs for my plugin:

using System.IO;

 namespace UnrealBuildTool.Rules
 {
     public class AndroidAPITemplate : ModuleRules
     {
         public AndroidAPITemplate(ReadOnlyTargetRules Target) : base(Target)
         {
             PublicIncludePaths.AddRange(
                 new string[] {
                     // ... add public include paths required here ...
                 }
                 );
 
             PrivateIncludePaths.AddRange(
                 new string[] {
                     "Developer/AndroidAPITemplate/Private",
                     // ... add other private include paths required here ...
                 }
                 );
 
             PublicDependencyModuleNames.AddRange(
                 new string[]
                 {
                     "Core",
                     "CoreUObject",
                     "Engine"
                     // ... add other public dependencies that you statically link with here ...
                 }
                 );
 
             PrivateDependencyModuleNames.AddRange(
                 new string[]
                 {                    
                     // ... add private dependencies that you statically link with here ...
                 }
                 );
 
             DynamicallyLoadedModuleNames.AddRange(
                 new string[]
                 {
                     // ... add any modules that your module loads dynamically here ...
                 }
                 );
                 
             PrivateIncludePathModuleNames.AddRange(
             new string[] {
                 "Settings",
                 "Launch",
             }
             );
 
 
             if (Target.Platform == UnrealTargetPlatform.IOS) {
             }
             else if(Target.Platform == UnrealTargetPlatform.Android)
             {
                 string PluginPath = Utils.MakePathRelativeTo(ModuleDirectory, Target.RelativeEnginePath);
                 AdditionalPropertiesForReceipt.Add(new ReceiptProperty("AndroidPlugin", Path.Combine(PluginPath, "AndroidAPITemplate_APL.xml")));
             }
         }
     }
 }