-1

I have a basic level at android, and I still have problems understanding the life cycle of apps. So I'm doing this test.

Let's say I have an app that has three classes: the MainActivity, class A and class B.

Class A receives "external" intents. I've defined the receiver in the manifest and it works well. Now, what I want is that, when class A receives and intent, it should send a "local" intent using LocalBroadcastManager. If I register the receiver on the Main Activity class it works (it receives the local intent), so I know the code for registering the receiver is ok. However, if I do it on class B, it never arrives. That is perfectly normal because I have never used/defined class B in any place, so, since class B is never executed in any way the receiver never gets registered.

Now, here are my questions (please, correct me if what I'm about to say is wrong, because I'm not sure I've understood it):

Since we don't know when the external intent will come, maybe the Main Activity (or the class B if it's defined as activity, for example) is destroyed. However, the intent will always arrive to class A because we put the receiver part in the manifest and it will broadcast the local intent. What should class A do so we are sure the other class receives it? (specially if I want that the receiver goes in class B) Should class B be something like a singleton, to be sure that one and only one class B exists, and then class A can check and create if needed class B before sending the intent? Would there be better way to do this? Maybe local broadcasts are not thought to be used in this cases (when the receiver maybe doesn't exist)?

In short, what I want is to have a class that is not in the main activity and that can be able to receive local broadcasted intents at any time, even if the app is not actively used and Android has destroyed/paused/etc it.

Thanks for your help!

Update: I'll put some code so I can show you what I've want.

First, this is class ExternalReceiver (what I previously called class A). This class just receives the external intent and broadcasts a local intent within my app:

public class ExternalReceiver extends BroadcastReceiver
{
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d("TestApp","ExternalReceiver: I've received the intent "+intent.getAction());
        Intent localIntent = new Intent("TestIntent");
        localIntent.putExtra("text", "Hello, I'm just a test");
        LocalBroadcastManager.getInstance(context).sendBroadcast(localIntent);
    }
}

Then, this is my MainActivity class. If I uncomment the registerReceiver, MainActivity would correctly receive the local intent and log the content of "text". My problem with this is that if the activity is destroyed, then the local intent wouldn't arrive here (I'd also prefere if another class is the receiver):

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d("TestApp","MainActivity - OnCreate()");
        // If I'd registered the receiver here, it would work as long as the activity exists:
        //LocalBroadcastManager.getInstance(this).registerReceiver(localReceiver, new IntentFilter("TestIntent"));
    }

    private BroadcastReceiver localReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.d("TestApp","MainActivity: I've received a local intent with text: "+intent.getStringExtra("text"));
        }
    };
}

Now, this is LocalReceiver (the class I've called B before). What I want is to receive the local intent here. Since I've never used this class (not in the manifest and not in the code) it will never arrive here, so right now it will never receive the intent. I've extended Activity too, but I haven't put it in the manifest. In fact, I don't need it to be an activity, but I thought maybe it would be good because then I could override onCreate. Suggestions are very welcome as how should I define this class:

public class LocalReceiver extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // I register the receiver.
        LocalBroadcastManager.getInstance(this).registerReceiver(localReceiver, new IntentFilter("TestIntent"));
    }

    private BroadcastReceiver localReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.d("TestApp","LocalReceiver: I've received a local intent with text: "+intent.getStringExtra("text"));
        }
    };
}

Finally this is my manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.testapp.localbroadcast"
    android:versionCode="2"
    android:versionName="@string/app_version" >

    <uses-sdk
        android:minSdkVersion="21"
        android:targetSdkVersion="21" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/testapp"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >

        <activity
            android:name="com.testapp.localbroadcast.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <receiver android:name="com.testapp.localbroadcast.ExternalReceiver" >
            <intent-filter>
                <action android:name="com.testapp.localbroadcast.TEST" />
            </intent-filter>
        </receiver>
    </application>
</manifest>

Now, to test everything, I'd send this intent through adb:

adb shell am broadcast -a com.testapp.localbroadcast.TEST -n com.testapp.localbroadcast/.ExternalReceiver

What I want:

  • Have a receiver on ExternalReceiver so it just listens to some intent (com.testapp.localbroadcast.TEST in my example). It works now.
  • ExternalReceiver then should broadcast a local intent to other class (LocalReceiver) within the app.
  • That class (LocalReceiver) receives the intent and then just do something (probably without even updating any UI).

My problem:

  • I want to be sure that the class that receives the local intent works even after a long time. For example, if the activity doesn't exists, then ExternalReceiver should do something to assure the other class receives the local intent. My guess: make LocalReceiver an activity and then, if needed, the ExternalReceiver class should start it if it doesn't exist. I still don't get how the ExternalReceiver works even if the MainActivity is destroyed. Shouldn't MainActivity be created or resumed as soon as any ExternalReceiver starts working?

I did a previous version of this within the Main Activity and everything worked ok as long as everything existed. Now I want to separate my code and make it ready to work even if Android has closed it. Maybe I haven't understood how this kind of things works, so any suggestion is very much welcome.

Thanks again for your help!

Solop
  • 13
  • 4
  • Please post your manifest, and class codes removing as much code as possible while reproducing the issue. Mention what you wish to see happen when what intent is received by what receiver. – gvijay Feb 06 '16 at 12:42
  • I've added code and more info about this. Thanks. – Solop Feb 06 '16 at 18:11

1 Answers1

0

You should put some line of code so that we can understand what you exactly need. Also this is code of class which receive Broadcast. Please put this as Global class. And put some code or exact your requirement for perfect solution.

public class AlarmReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
      //Boradcast your local contents from here
    }
}
Ashish Vora
  • 571
  • 1
  • 8
  • 27
  • 1
    I've put a better explanation and some code in my post. My main problem is to be sure the the register of the receiver works when the intent arrives (specially meaning that Android, or even the user, may have destroyed the activities of my app). Thanks. – Solop Feb 06 '16 at 18:12
  • 1
    All you need to put is that make a global Broadcast Receiver as i suggested. As you receive Broadcast open your Activity whether its Activity A or Activity B using Intent. Thats it...! – Ashish Vora Feb 08 '16 at 04:55
  • Yep, I guess this is the way to go. I'm not sure if using global classes is good practice or not, but it works very well. Thanks. Btw (not related to you, Ashish), I'm a little bit surprised this question got downvoted even after posting a coded example (to be honest, I think that just my first explanation of the problem was enough). Anyway, next time I'll try to thoroughly explain my question. – Solop Feb 15 '16 at 16:35
  • 1
    Yup. But finally you got solution. Also if you are developing where most of Broadcasting is used then you should use Global Broadcast Receiver then redirect to Activity. It will help you to have centralized code and modification at any stage will be easy. – Ashish Vora Feb 16 '16 at 07:22