[SOLVED] LAMW: how to declare receivers in Manifests lazarus / 43-Android ---------------------------------------------------------------------- jluixjurado · 2022-09-21 13:17 Hi there! I'm trying to declare an SMS receiver in my app androidmanifest.xml. The reason for that is that if I use a jBroadcastReceiver it only works when the app is running, but the app is not opened when a new SMS is coming an the app is not working, as it seems to use the context-register receivers approach (https://developer.android.com/guide/components/broadcasts) The problem is that: I add these lines to the androidmanifest.xml:                                 But, when an SMS comes, the following message appears in catlog and the app crashes: java.lang.RuntimeException: Unable to instantiate receiver es.jluixjurado.alejandriasmsrecibidos.jBroadcastReceiver ... jBroadcastReceiver has no zero argument constructor I've tried to learn by the Demos, but the only one related I've found is in AppSMSWidgetProviderDemo1. The problem is that, although when I drop a jSMSWidgetProvider in my app it automagically adds these lines to the manifest:     and the app doesn't crash anymore, The system doesn't open the app when a sms arrives and the app is closed. Any idea? Thanks in advance. ---------------------------------------------------------------------- jluixjurado · 2022-09-21 14:53 Ok. I've advenced (a bit). I've added the constructor      public jBroadcastReceiver() {} to the file ..\lazandroidmodulewizard\android_wizard\smartdesigner\jav a\jBroadcastReceiver.java and, now, when receiving the SMS the error in logcat is:      java.lang.NullPointerException: Attempt to invoke virtual method 'void ...Controls.pOnBroadcastReceiver(long, android.content.Intent)' on a null object reference So, the missing part is that I need to instantiate the object!!! But, how? I've already seen the file  ..\lazandroidmodulewizard\android_wiz ard\smartdesigner\java\jBroadcastReceiver.create, with the content      public java.lang.Object jBroadcastReceiver_jCreate(long _Self) {         return (java.lang.Object)(new jBroadcastReceiver(this,_Self));      } but I'm not sure what I should do. Any help would be greatly appreciated! ---------------------------------------------------------------------- jluixjurado · 2022-09-21 22:14 After many (many) attempts, this id how far I've reached: Change the originalonReceive method in jBroadcastReceiver with this:    @Override    /*.*/public void onReceive(Context ctx, Intent intent) {       mResultCode = 0;       switch (this.getResultCode()) {            case Activity.RESULT_OK: mResultCode = -1; break;            case Activity.RESULT_CANCELED: mResultCode = 0; break;        }                          mResultData = this.getResultData();                             mResultExtras = this.getResultExtras(true);                //controls.pOnBroadcastReceiver(pascalObj,  intent); //jluixjurado       //--------------------------------------jluixjurado          if (controls != null) {             controls.pOnBroadcastReceiver(pascalObj,  intent); //normal behaviour          } else {             String packageName = ctx.getPackageName();             Intent appIntent = new Intent();                    appIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);             ComponentName cn = new ComponentName(packageName, packageName+".App");             appIntent.setComponent(cn);             PendingIntent pendingIntent = PendingIntent.getActivity(ctx, 0, appIntent, PendingIntent.FLAG_UPDATE_CURRENT); //FLAG_CANCEL_CURRENT);                   try {                // Perform the operation associated with our pendingIntent                pendingIntent.send();             } catch (PendingIntent.CanceledException e) {                e.printStackTrace();             }                      Log.d("BroadcastReceiver","Intent -> "+packageName+".App");          }                  //--------------------------------------jluixjurado    } This way the app doesn't crash when not running and a SMS is received, but it doesn't release the main activity (and I don't know why, because the intend seems to be ok). I've tried a variant with the same outcome:    @Override    /*.*/public void onReceive(Context ctx, Intent intent) {       mResultCode = 0;       switch (this.getResultCode()) {            case Activity.RESULT_OK: mResultCode = -1; break;            case Activity.RESULT_CANCELED: mResultCode = 0; break;        }                          mResultData = this.getResultData();                             mResultExtras = this.getResultExtras(true);                //controls.pOnBroadcastReceiver(pascalObj,  intent); //jluixjurado         //--------------------------------------jluixjurado               if (controls != null) {             controls.pOnBroadcastReceiver(pascalObj,  intent); //normal behaviour          } else {             String packageName = ctx.getPackageName();             Intent appIntent = new Intent(packageName+".App");             Intent appIntent = new Intent();             appIntent.setClassName(packageName,packageName+".App");                //if (priorIntent != null) appIntent.putExtras(intent);             appIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);             ctx.startActivity(appIntent);             Log.d("BroadcastReceiver","Intent -> "+packageName+".App");          }                  //--------------------------------------jluixjurado      } I'm a bit frustrated right now... ---------------------------------------------------------------------- jluixjurado · 2022-09-25 21:01 Hi there! I've finally got it! The main problem was that from Android 10 (API level 29), there is a restriction for starting activities from the background (https://developer.android.com/guide/components/activities/background- starts). In that link you can read that, to overcome that restriction, your application has to obtain the permission SYSTEM_ALERT_WINDOW (@jmpessoa , Could it be possible to add that permission to the list on Proyect -> Proyect properties -> [LAMW] Android Project Properties, so we don't have to insert it manually in AndroidManifest.xml?) So, let's add it to AndroidManifest.xml:         After that, we add our Manifest-declared receivers to the AndroidManifest.xml file like, for instance, this one to be notified when a SMS is received:                                 Then, we change the code of ../android_wizard/smartdesigner/java/jBroadcastReciever.java:      The line           controls.pOnBroadcastReceiver(pascalObj,  intent);      turns into:          if (controls != null) {             controls.pOnBroadcastReceiver(pascalObj,  intent); //normal behaviour          } else {             Context appContext = ctx.getApplicationContext();             String packageName = appContext.getPackageName();             Intent appIntent = new Intent();             appIntent.setClassName(packageName,packageName+".App");                  appIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);                  appIntent.putExtras(intent);                  appContext.startActivity(appIntent);          } In essence, the new code does the same thing if the app which owns the jBroadcastReceiver is up and running but, if it isn't, the main activity of that App is started, and the bundle of the broadcast intent is copied to the new intent in charge of starting the activity. The App is started and the OnActivityCreate method of the main activity is called, giving it the new intent. As that intent IS NOT a broadcast one, we shouldn't called with it directly the jBroadcastReceiver OnReceiver method. Instead, inside OnActivityCreate we should do something like this:      procedure TMainModule.OnActivityCreate(Sender: TObject; intentData: jObject);           var           bundle : jObject;           newIntent : jObject; //new SMS_RECEIVED [or any other broadcast event you want to handle] intent      begin           bundle := IntentManager.GetExtraBundle(intentData);           IntentManager.NewIntent();           IntentManager.SetAction('android.provider.Telephony.SMS_RECEIVED');           IntentManager.PutExtraBundle(bundle); //put the intentData extras bundle inside the newIntent           newIntent := IntentManager.GetIntent();          OnReceiver(self, newIntent); //now we can call the jBroadcastReceiver OnReceiver method      end; I hope it can be helpful to someone. @jmpessoa: It would be great if you consider to change the jBroadcastReceiver.java in Github, as it doesn't change the normal behaviour of the component and gives it more functionality (and, of course, that way it wouldn't erase my modifications in the next LAMW update  ). Thanks in advance. ---------------------------------------------------------------------- jmpessoa · 2022-09-25 23:08 QuoteIt would be great if you consider to change the jBroadcastReceiver.java in Github... I will do!  Thank you!