简体   繁体   中英

Launching an intent without context

What is the best way to deal with the following situation: I have a IntentService which does synchronisation with the server (this is triggered by either an Activity coming to the foreground, or a GCM message, so onoy occasional). Sometimes there is a user action needed as a result, and the given command/request is part of the response XML.

There are basically two options, it is either a yes/no question, or a full Activity to for example select the desired language.

How can I do this, or what would be the best way? If I try to launch the Activity with the context of the IntentService nothing happens. I could write a abstract Activity, which I extends in all my Activities and sent a broadcast message which those receive and subsequent start the Activity form the activity which is active, but don't know if that is the best way to do it in Android.

Any suggestions would be appreciated!

[EDIT: as suggested some code]

public class SyncService extends IntentService{

    public SyncService(){
        super("SyncService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
            iDomsAndroidApp app = ((iDomsAndroidApp) getApplicationContext());
            DataManager manager = app.getDataManager();
            manager.updateData(this);
    }
}


public class DataManager {

    // For brevity, this is called with the DOM.Document with the actions to be preformed
    private void checkForActions(Document doc, SyncUpdateInterface syncInterface){
        NodeList objects = null;
        NodeList rootNodes = doc.getElementsByTagName("actions");

        for (int j = 0; j < rootNodes.getLength(); j++) {
            Element rootElement = (Element) rootNodes.item(j);
            if (!rootElement.getParentNode().getNodeName().equals("iDoms")) {
                continue;
            }
            objects = ((Element) rootNodes.item(j)).getElementsByTagName("action");
            break;
        }

        if(objects == null || objects.getLength() == 0){
            Log.d(iDomsAndroidApp.TAG, "No actions");
            return;
        }


        for (int j = 0; j < objects.getLength(); j++) {
            Element element = (Element) objects.item(j);
            String action = ((Element) element.getElementsByTagName("command").item(0)).getTextContent();
            if(action == null) return;
            Log.d(iDomsAndroidApp.TAG, "Action: " + action);
            try{
                if(action.equalsIgnoreCase("selectLanguage")){
                    if(syncInterface == null || syncInterface.getContext() == null) throw new Exception("No context, so cannot perform action");
                    iDomsAndroidApp app = ((iDomsAndroidApp) iDomsAndroidApp.getAppContext());
                    // The app.actionIntent is just a central function to pick the right intent for an action.
                    syncInterface.getContext().startActivity(app.actionIntent("settings", iDomsAndroidApp.context));
                } else if (action.equalsIgnoreCase("markAllAsRead")) {
                    if(syncInterface == null | syncInterface.getContext() == null) throw new Exception("No context, so cannot perform action");
                    AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(syncInterface.getContext());
                    alertDialogBuilder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int id) {
                            // User clicked OK, so save the result somewhere
                            // or return them to the component that opened the dialog
                            iDomsAndroidApp app = ((iDomsAndroidApp) iDomsAndroidApp.getAppContext());
                            app.getDataManager().markAllAsRead(null);
                        }
                    });
                    alertDialogBuilder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int id) {

                        }
                    });

                    alertDialogBuilder.setTitle(iDomsAndroidApp.context.getString(R.string.markAllAsRead));
                    alertDialogBuilder.setMessage(iDomsAndroidApp.context.getString(R.string.markAllAsReadText));

                    alertDialogBuilder.show();
                }
            } catch (Exception e){
                Log.w(iDomsAndroidApp.TAG, "Problem performing the action " + element.getTextContent(), e);
                sentCrashReport("Problem performing the action " + element.getTextContent(), e);
            }
        }
}

I tried using the my SyncInterface, as it gives the context of the IntentService, but think it is a but clumsy and doesn't work:

public interface SyncUpdateInterface {
    public void doProgress(String message, int increment, int total);
    public void doProgress(String message, int increment);
    public void doProgress(String message);
    public Context getContext();
}

You might have to rethink your approach. The intentservice only lives for the duration of the onHandleIntent() method. That is to say, once the last line of code of the onHandleIntent() method is reached, the IntentService stops itself.

Try EventBus. It provides a solution to similar problems by making communication between components (Activities, Services, Standalone classes) of an application.

Use Gradle to import library

compile 'org.greenrobot:eventbus:3.1.1'

Define an event

public class MessageEvent { /* Additional fields if needed */ }

Launch Event using

EventBus.getDefault().post(new MessageEvent());

Register component to receive event

 @Override
 public void onStart() {
     super.onStart();
     EventBus.getDefault().register(this);
 }

 @Override
 public void onStop() {
     super.onStop();
     EventBus.getDefault().unregister(this);
 }

Receive launched even by declaring this method

@Subscribe(threadMode = ThreadMode.MAIN)  
public void onMessageEvent(MessageEvent event) {/* Do something */};

For more information visit https://github.com/greenrobot/EventBus

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM