'java.lang.String android.content.Context.getP

2019-04-14 20:57发布

问题:

My alarmManager is in the MainActivity it fires every 30 second to the MyReceiver class then from it I start the GetLLRD IntentService class. Thereafter, I am sending a request from the onHandleIntent method to the Server following which I am getting a Response. Now I want to achieve the following, every time the alarmManager fires in the MainActivity I want to pass the Intent from the Response from the Server in the GetLLRD class to the Map class.

I have tried it twice with the intent's code in the GetLLRD class with this part Intent intent1 = new Intent(this, Map.class); I received the intent just once in the Map activity. With this one Intent intent1 = new Intent(mContext, Map.class); the app crashes and I got this error below. How can I achieve my purposes?

Error:

07-08 13:04:33.482: E/AndroidRuntime(16838): FATAL EXCEPTION: IntentService[IntentService]
07-08 13:04:33.482: E/AndroidRuntime(16838): Process: com.bustracker, PID: 16838
07-08 13:04:33.482: E/AndroidRuntime(16838): java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object reference
07-08 13:04:33.482: E/AndroidRuntime(16838):    at android.content.ComponentName.<init>(ComponentName.java:77)
07-08 13:04:33.482: E/AndroidRuntime(16838):    at android.content.Intent.<init>(Intent.java:4570)
07-08 13:04:33.482: E/AndroidRuntime(16838):    at com.bustracker.GetLLRD.onHandleIntent(GetLLRD.java:98)
07-08 13:04:33.482: E/AndroidRuntime(16838):    at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:65)
07-08 13:04:33.482: E/AndroidRuntime(16838):    at android.os.Handler.dispatchMessage(Handler.java:102)
07-08 13:04:33.482: E/AndroidRuntime(16838):    at android.os.Looper.loop(Looper.java:145)
07-08 13:04:33.482: E/AndroidRuntime(16838):    at android.os.HandlerThread.run(HandlerThread.java:61)

MainActivity:

public class MainActivity extends ActionBarActivity{
        Context context;

                    getLRLD.received_MainActvity_Context(context);
                    Intent intent = new Intent(MainActivity.this,
                            IntentReceiver.class);
                    intent.putExtra("json_data", json);
                    PendingIntent pendingIntent = PendingIntent.getBroadcast(
                            getApplicationContext(), 1, intent,
                            PendingIntent.FLAG_UPDATE_CURRENT);
                    AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
                    Calendar cal = Calendar.getInstance();
                    alarm.setRepeating(AlarmManager.RTC_WAKEUP,
                            System.currentTimeMillis(), 30 * 1000,
                            pendingIntent);
                  startService(intent);

 }

MyReceiver class:

public class MyReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        try {
            String action = intent.getStringExtra("json_data");

            if (!action.isEmpty()) {

                startService(context, action);

            }
        } catch (Exception e) {
        }
    }

    public void startService(Context context, String action) {
        Intent inetent = new Intent(context, GetLLRD.class);
        inetent.putExtra("json_data", action);
        context.startService(inetent);
    }

}

GetLLRD class:

public class GetLLRD extends IntentService {
    Context mContext;

    public GetLLRD() {
        super("IntentService");

    }
    public void received_MainActvity_Context(Context context){
        this.mContext = context;


    }

    @Override
    protected void onHandleIntent(Intent intent) {

        String jSONString = intent.getStringExtra("json_data");

        if (jSONString != null) {
                 //So if I try it in this way I am just receiving the data intent just once in the Map activity.
                             Intent intent1 = new Intent(this, Map.class);
                             intent1.putExtra("list_data", data);
                             intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                             startActivity(intent1);

               //When I do it in this way I am getting the error above:
                             Intent intent1 = new Intent(mContext, Map.class);
                             intent1.putExtra("list_data", data);
                             intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                             mContext.startActivity(intent1);

        }
    }
 }

Map activity:

public class Map extends ActionBarActivity{

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            // TODO Auto-generated method stub
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);

            Intent intent = getIntent();        
            @SuppressWarnings("unchecked")
             ArrayList<ItemDTO> list =(ArrayList<ItemDTO>) intent.getSerializableExtra("list_data");
                for (ItemDTO itemDTO : list) {
                    double latitude = itemDTO.getLatitude();
                    double longitude = itemDTO.getLongitude();
                    int route = itemDTO.getRoute();
                    String direction = itemDTO.getDirection();
                    System.out.println("test from Map activity:  " + latitude + ", " + longitude
                            + ", " + ", " + route + ", " + direction);

                }
        }       
    }

Edit:

GetLLRD IntentService class:

            if (data != null && !data.isEmpty()) {
                                            Intent localIntent = new Intent(
                                Constants.BROADCAST_ACTION).putExtra(
                                "data_list", data);
                        LocalBroadcastManager.getInstance(this).sendBroadcast(localIntent);
            } 

Inside the Map activity:

onCraete(Bundle savedInstanceState){
        IntentFilter data_filter = new IntentFilter();
        data_filter.addAction(Constants.BROADCAST_ACTION);
        registerReceiver(data_receiver, data_filter);
}


final BroadcastReceiver data_receiver = new BroadcastReceiver() {

    @Override
    public void onReceive(Context context, Intent intent) {
        @SuppressWarnings("unchecked")
        ArrayList<ItemDTO> list = (ArrayList<ItemDTO>) intent
                .getSerializableExtra("list_data");
        for (ItemDTO itemDTO : list) {
            double latitude = itemDTO.getLatitude();
            double longitude = itemDTO.getLongitude();
            int route = itemDTO.getRoute();
            String direction = itemDTO.getDirection();
            System.out.println("test from Apple activity:  " + latitude
                    + ", " + longitude + ", " + ", " + route + ", "
                    + direction);

        }

    }

};

回答1:

Your architecture is flawed. The IntentService is created when you call startService(). Then onCreate() and onHandleIntent() is called in the Service. Upon completion of onHandleIntent(), if there are no other pending Intents to be processed the Service stops.

You are making this call in MainActivity before you call startService():

getLRLD.received_MainActvity_Context(context);

You don't show how you are setting the reference variable getLRLD, but this isn't going to work. The Service isn't actually created until you call startService().

You are trying to establish a communcations channel between the Service and the Activity. However, you are using IntentService which is a non-persistent Service. It gets created as needed and when it has nothing to do it goes away. You therefore cannot pass a reference to the Service to the Activity, and you also should not pass a reference to the Activity to the Service.

The best way to achieve communication between the Service and the Activity is one of the following:

  1. Service sends a broadcast Intent with the data. The Activity can register a BroadcastRecevier to listen for this.

  2. Activity creates a PendingIntent containing the necessary ACTION, COMPONENT, etc. and passes this to the Service as an "extra" in the Intent it uses when calling startService(). The Service calls send() on that PendingIntent in order to return data to the Activity.

In both cases the Service doesn't need to know anything about the Activity, and the Activity doesn't need a reference to the Service.

EDIT: Add code to start Activity

If you want to start an Activity, you can do this in the Service.onHandleIntent():

Intent intent1 = new Intent(this, Map.class);
intent1.putExtra("list_data", data);
intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
              Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent1);

Using Intent.FLAG_ACTIVITY_SINGLE_TOP will prevent Android from launching a new instance of the Activity, if there is already an instance of the Activity running. In case the Activity is already running, you can get the "extras" from the Intent by overriding onNewIntent() in the Activity.

If you use this approach you don't need to use the broadcast Intent to send the data from the Service to the Activity.