Recent

Author Topic: [SOLVED] LAMW: how to declare receivers in Manifests  (Read 936 times)

jluixjurado

  • New Member
  • *
  • Posts: 21
[SOLVED] LAMW: how to declare receivers in Manifests
« on: September 21, 2022, 03:17:59 pm »
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:

   <receiver android:name=".jSMSWidgetProvider" android:label="@string/app_name">
      <intent-filter>
         <action android:name="android.provider.Telephony.SMS_RECEIVED"/>
      </intent-filter>
   </receiver>

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:

<receiver android:name=".jSMSWidgetProvider" android:label="@string/app_name"><intent-filter><action android:name="android.appwidget.action.APPWIDGET_UPDATE"/></intent-filter><intent-filter><action android:name="es.jluixjurado.alejandriasmsrecibidos.LAMW_SMS_WIDGET_NOTIFY"/></intent-filter><intent-filter><action android:name="android.provider.Telephony.SMS_RECEIVED"/></intent-filter><meta-data android:name="android.appwidget.provider" android:resource="@xml/jsmswidgetprovider_info"/></receiver>   

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.
« Last Edit: September 29, 2022, 05:39:06 pm by jluixjurado »

jluixjurado

  • New Member
  • *
  • Posts: 21
Re: LAMW: how to declare receivers in Manifests
« Reply #1 on: September 21, 2022, 04:53:43 pm »
Ok. I've advenced (a bit).

I've added the constructor

     public jBroadcastReceiver() {}

to the file ..\lazandroidmodulewizard\android_wizard\smartdesigner\java\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_wizard\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!   
« Last Edit: September 21, 2022, 05:05:27 pm by jluixjurado »

jluixjurado

  • New Member
  • *
  • Posts: 21
Re: LAMW: how to declare receivers in Manifests
« Reply #2 on: September 22, 2022, 12:14:49 am »
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

  • New Member
  • *
  • Posts: 21
Re: LAMW: how to declare receivers in Manifests
« Reply #3 on: September 25, 2022, 11:01:47 pm »
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:

       <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

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:

   <receiver
      android:name=".jBroadcastReceiver"
      android:label="@string/app_name">
      <intent-filter android:priority="1000">
         <action android:name="android.provider.Telephony.SMS_RECEIVED" />
      </intent-filter>
   </receiver>

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

  • Hero Member
  • *****
  • Posts: 2297
Re: LAMW: how to declare receivers in Manifests
« Reply #4 on: September 26, 2022, 01:08:04 am »
Quote
It would be great if you consider to change the jBroadcastReceiver.java in Github...

I will do! 


Thank you!
Lamw: Lazarus Android Module Wizard
https://github.com/jmpessoa/lazandroidmodulewizard

 

TinyPortal © 2005-2018