5

I have read this answer here and also this here and I'm trying to figure out what fits best for my case.

I start a Service inside onCreate() where I make an HTTP requests and I get an id as a response. I then broadcast this id and receive it in my activity.

The problem is that the user can obviously navigate to another activity just by opening the drawer and selecting an option and I can miss the broadcast.

I can obviously have all my Activities extend an abstract class which extends Activity like is mentioned here but I'm not 100% sure its the best solution. What if user decides to quit the app before I receive the id ?

Edit : app architecture

  • User captures an image using an Intent to open camera app and get the path of the image file.
  • FormActivity starts where user can add some details about the image.
  • User clicks upload and I pass the data user has just entered to QuizActivity.
  • In onCreate() of QuizActivity I start an Service where I :
    • create an empty entry to server and I get an id as a response and
    • upload image to server
  • That id I get as a response from server I then broadcast it.
  • QuizActivity has an entryIdReceiver registered where receives the id and stores it in a private field until user decides to either leave the activity or click to upload the quiz ( if he entered data for the quiz of course )
  • If user clicks upload I start an IntentService with the id and the quiz data.
  • If User opens drawer and select another Activity or clicks cancel to create a quiz I start an IntentService to upload the id with the "empty quiz data" and move user to MainActivity.

The problem is : what if uer closes app while on QuizActivity and I haven't yet receive the id, or user decides to got to another Activity using the drawer without adding a quiz. I still have to start a service and upload the id with "empty quiz data".

Community
  • 1
  • 1
Mes
  • 1,671
  • 3
  • 20
  • 36
  • Why are you not making the network call in the `Activity`? – Xaver Kapeller Jul 13 '16 at 16:20
  • Is it absolutely necessary for the `Activity` to receive the id? The broadcasts in general are out of the question. – Xaver Kapeller Jul 13 '16 at 16:21
  • @XaverKapeller so I can "listen" to other Activities too just in case user decides to leave the `Activity` – Mes Jul 13 '16 at 16:21
  • @XaverKapeller no its not absolutely necessary for the `Activity` to receive it. I just need it till I got also some other info from the user and start an `IntentService` – Mes Jul 13 '16 at 16:23
  • 1
    There are far better ways to do this. When I get home I can write an answer to this question and suggest you a proper architecture for your app. – Xaver Kapeller Jul 13 '16 at 16:23
  • Can you please explain the whole architecture of your app to me? I also need to know what your app does exactly. – Xaver Kapeller Jul 13 '16 at 16:24
  • @XaverKapeller ok thanks a lot. I'm waiting for your answer when you 've got time! :) – Mes Jul 13 '16 at 16:24
  • @XaverKapeller I'll edit the post and give more details asap. – Mes Jul 13 '16 at 16:25
  • @XaverKapeller I have edited the post with more info about what app does and how I'm doing it. I await for your reply. – Mes Jul 13 '16 at 17:10
  • No matter what you do, you have to deal with the case "you got the id, but you can't do anything after then" since you can't prevent the user from kilingl your app, for example. – suitianshi Jul 21 '16 at 02:12
  • One solution can be that you start a service and also bind to it in your QuizActivity. When your QuizActivity will finish (either by moving to some other activity or by killing app) your service will know (in onUnbind() method) that activity has finished and you can send data accordingly. You can try this solution and let me know if its working as I haven't tried this. Also remember to start a sticky service so that if app is killed your service restarts (if needed). – Ankit Aggarwal Jul 21 '16 at 06:05
  • I don't understand why are you even bothering using `Broadcasts` and `Services`?! why don't you just start a new `Thread` inside your activity and pass your `Context` to it and when you received the "ID" store it in `SharedPreferences`? this way by using new `Thread` even if you call `finish()` and completely destroy your app, it will continue it's task of receiving and storing the "ID" in the background. – M D P Jul 24 '16 at 21:00

2 Answers2

2

It's pretty good, by using abstract class, where you handle all action, and just send callback to your activity. Using that example in your question above seems to me like EventBus.

And even better using special class and interfaces, instead of abstract class, because you may want use FragmentActivity, AppCombatActivity, etc.

For example, your have your own class, which receiving result from your service and send all registered to him activities. Invoking result from net requests with interfaces:

public class NetRequestReceiver extends BroadcastReceiver {

private List<Activities> registeredActivities;

public static void getInstance () {
    //Continue singleton initialing!
    //....
}

@Override
public void onReceive(Context context, Intent intent) {
    for (Activity act : registeredActivities) {
         if (act instanceOf ReceivingCallback) {
             act.onReceiveMessage(intent);
         } else throw Exception("Activity missing ReceivingCallback");
    }
}    

public void registerActivity (Activity, activity) {
    if (!registeredActivities.contains(activity)) {
        registeredActivities.add(activity);
    }
}

public void unRegisterActivity (Activity, activity) {
    if (registeredActivities.contains(activity)) {
        registeredActivities.remove(activity);
    }
}

public interface ReceivingCallback {
    onReceiveMessage (Intent intent);
}

}

Then in all you activities add next listener. But (!) don't forget register receiver above in you Service for receiving result!

public class MainActivity extends Activity implements NetRequestReceiver.ReceivingCallback {

public void onStop () {
    super.onStop()
    NetRequestReceiver.getInstance().unRegisterActivity(this);
}

public void onResume () {
    super.onResume()
    NetRequestReceiver.getInstance().registerActivity(this);
}

@Override
public onReceiveMessage (Intent intent) {
   //put here whaterver you want your activity 
   //to do with the intent received
}
}

What do you think, we get, using design above? We now have single Receiver and Callback as an interface. So you can use Fragment, Activity, FragmentActivity, and other class, for receiving result from Service via Broadcast and (!) without copy pasting same behavior!

Also it's looks nice, because we split of different layer - presentation, view, and receiver. You call net request in Service. This Service send result to Broadcast, and then he sends data to all registered activities.

Yes, it's seems like EventBus, but based on your question it's just what you need for listen connection from service to different activities, and with better structure.

GensaGames
  • 5,538
  • 4
  • 24
  • 53
1

Maybe you can send a sticky broadcast. The system will keep it even the activity destroyed and you can receive the intent immediately when your register property receiver.

But notice sendStickyBroadcast is deprecated and don't forget declare

android.permission.BROADCAST_STICKY

in your AndroidManifest.xml if you decide to using it.

Huang Wei
  • 39
  • 3