Starting new Activity using Intent. NPE at android

2019-09-06 19:47发布

问题:

I'm trying to start a new Activity using an Intent. I've done this successfully in a different app, but that approach doesn't seem to work in this case?

This is my code...

 public void startLevelEnd(Context context){
     Intent myIntent = new Intent(FirstActivity.this, LevelEndPanel.class);
     FirstActivity.this.startActivity(myIntent);
 }

From my AndroidManifest.xml file...

<activity android:label="@string/app_name" android:name=".LevelEndPanel"></activity>

And I call the startLevelEnd() routine (fromout a different class) using...

FirstActivity.startLevelEnd(this);

I get a NullPointerException error on the line "Intent myIntent..." (from code snippet above) :

04-16 09:46:39.361: E/AndroidRuntime(475):  at android.content.ContextWrapper.getPackageName(ContextWrapper.java:120)

Full Log :

04-16 14:32:32.870: E/AndroidRuntime(336): FATAL EXCEPTION: main
04-16 14:32:32.870: E/AndroidRuntime(336): java.lang.NullPointerException
04-16 14:32:32.870: E/AndroidRuntime(336):  at android.content.ContextWrapper.getPackageName(ContextWrapper.java:120)
04-16 14:32:32.870: E/AndroidRuntime(336):  at android.content.ComponentName.<init>(ComponentName.java:75)
04-16 14:32:32.870: E/AndroidRuntime(336):  at android.content.Intent.<init>(Intent.java:2702)
04-16 14:32:32.870: E/AndroidRuntime(336):  at happyworx.nl.App.FirstActivity.startLevelEnd(FirstActivity.java:32)
04-16 14:32:32.870: E/AndroidRuntime(336):  at happyworx.nl.App.model.components.GameManager.LevelEnd(GameManager.java:89)
04-16 14:32:32.870: E/AndroidRuntime(336):  at happyworx.nl.App.model.components.GameManager$1.run(GameManager.java:60)
04-16 14:32:32.870: E/AndroidRuntime(336):  at android.os.Handler.handleCallback(Handler.java:587)
04-16 14:32:32.870: E/AndroidRuntime(336):  at android.os.Handler.dispatchMessage(Handler.java:92)
04-16 14:32:32.870: E/AndroidRuntime(336):  at android.os.Looper.loop(Looper.java:123)
04-16 14:32:32.870: E/AndroidRuntime(336):  at android.app.ActivityThread.main(ActivityThread.java:3683)
04-16 14:32:32.870: E/AndroidRuntime(336):  at java.lang.reflect.Method.invokeNative(Native Method)
04-16 14:32:32.870: E/AndroidRuntime(336):  at java.lang.reflect.Method.invoke(Method.java:507)
04-16 14:32:32.870: E/AndroidRuntime(336):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
04-16 14:32:32.870: E/AndroidRuntime(336):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
04-16 14:32:32.870: E/AndroidRuntime(336):  at dalvik.system.NativeStart.main(Native Method)

For @Sergi, the full class containing the method :

package happyworx.nl.Appelz.model.components;


import happyworx.nl.Appelz.AppelzActivity;
import happyworx.nl.Appelz.LevelEndPanel;
import happyworx.nl.Appelz.MainGamePanel;
import happyworx.nl.Appelz.MainThread;
import happyworx.nl.Appelz.R;
import happyworx.nl.Appelz.model.apple;
import happyworx.nl.Appelz.model.glyphs;


import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import android.app.Activity;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.os.Handler;
import android.util.Log;


public class GameManager extends Activity {

    //Declare Vars
    private static final String TAG = "GameManager";
    public static MainGamePanel panel;
    private static glyphs glyphsCount;
    public static GameManager GameManager = new GameManager();

    public static AppelzActivity AppelzActivity = new AppelzActivity();

    private static Canvas canvas;
    final static int delayMillis = 1000;
    public static boolean count = false;
    public static int i = 6;
    public final static Handler handler = new Handler();


    public final static Runnable runnable = new Runnable()  {

        @Override
        public void run()
        {

            if (SlotManager.alSlottedFruitList.size() > 0){
            //TODO Create Full screen countdown timer
                Log.d("", "Countdown Timer in GameManager " + i);

                i--;
                if (count && i > -1) // stop timer when count is false
                {
                    handler.postDelayed(runnable, 1000);
                } else {
                    if (i == -1){
                        Log.d("", "RoundUp the Level");

                        GameManager.LevelEnd();
                    }
                    // reset Countdown (if basket outside checkout)
                    i = 6;
                }
            } else {
                // reset Countdown (if slot has no fruits)
                i = 6;
            }
        }
    };


    public void LevelEnd(){
        // First, count the Fruits in the slot
        SlotManager.countSlotInv();
        List<Integer> list = new ArrayList<Integer>();


        // Fill itemIds with the types of fruits
        for (apple a : SlotManager.alSlottedFruitList){
            Integer itemId = Integer.valueOf(a.FruitType);
            list.add(itemId);

            Set<Integer> unique = new HashSet<Integer>(list);
        }
            for (int key = 0; key < 3 ; key++) {
                System.out.println(key + " : " + Collections.frequency(list, key));     
            }
            startLevelEnd();
    }

    public void startLevelEnd(){
         Intent myIntent = new Intent(this, LevelEndPanel.class);
         this.startActivity(myIntent);
     }

    public GameManager() 
    {
    }

The LevelEndPanel class :

package happyworx.nl.Appelz;


import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;



public class LevelEndPanel extends Activity implements OnClickListener {

 private static final String TAG = LevelEndPanel.class.getSimpleName();
 private Button btnNewMission;

 public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.level);

        btnNewMission = (Button) findViewById(R.id.btnNewMission);
        btnNewMission.setOnClickListener(new Button.OnClickListener() {
            public void onClick(View arg0) {
                Intent i = new Intent(getApplicationContext(), AppelzActivity.class);
                startActivity(i);
            }});


 }


@Override
public void onClick(View v) {
    // TODO Auto-generated method stub

}

}

And the MainThread :

package happyworx.nl.Appelz;

import android.graphics.Canvas;
import android.util.Log;
import android.view.SurfaceHolder;

public class MainThread extends Thread {

 private static final String TAG = MainThread.class.getSimpleName();

 private SurfaceHolder surfaceHolder;
 private MainGamePanel gamePanel;
 public static boolean running;
 public static Canvas canvas;

 public void setRunning(boolean running) {
 MainThread.running = running;
 }

 public MainThread(SurfaceHolder surfaceHolder, MainGamePanel gamePanel) {
  super();
  this.surfaceHolder = surfaceHolder;
  this.gamePanel = gamePanel;

 }

 @Override
 public void run() {
     // Canvas canvas;
      Log.d(TAG, "Starting game loop");
      while (running) {
      MainThread.canvas = null;
       // try locking the canvas for exclusive pixel editing on the surface
       try {
           MainThread.canvas = this.surfaceHolder.lockCanvas();
        synchronized (surfaceHolder) {
         // update game state
         this.gamePanel.update();
         // render state to the screen
         // draws the canvas on the panel
         this.gamePanel.onDraw(MainThread.canvas);
        }
       } finally {
        // in case of an exception the surface is not left in
        // an inconsistent state
        if (MainThread.canvas != null) {
         surfaceHolder.unlockCanvasAndPost(MainThread.canvas);
        }
       } // end finally
      }
     }
}

And the basket class, which starts the CountDown timer in GameManager (maybe here is my error?!?)

package happyworx.nl.Appelz.model;

import happyworx.nl.Appelz.MainGamePanel;
import happyworx.nl.Appelz.model.components.GameManager;
import happyworx.nl.Appelz.model.components.SlotManager;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.util.Log;
import android.view.MotionEvent;

public class basket {

 private Bitmap bitmap; // the actual bitmap
 private int x;   // the X coordinate
 private int y;   // the Y coordinate'
 public static int width;
 public static int height;
 public float X = 100;
 public float Y = 100;

 private boolean touched; // if droid is touched/picked up

 public basket(Bitmap bitmap, int x, int y) {
  this.bitmap = bitmap;

  width = bitmap.getWidth(); 
  height = bitmap.getHeight(); 
 }

 public Bitmap getBitmap() {
  return bitmap;
 }
 public void setBitmap(Bitmap bitmap) {
  this.bitmap = bitmap;
 }

 public int getWidth(){
      return bitmap.getWidth();
     }

     public int getHeight(){
      return bitmap.getHeight();
     }

 public int getX() {
  return x;
 }



 public void setX(float x) {

    // if basket is further than slotmargin 
     if (x + width/2 > SlotManager.SlotmarginX) {
        // if basket is NOT in CheckOut area    
         if (this.Y < MainGamePanel.height - 80 - height/2){
            x = SlotManager.SlotmarginX - width/2;

        } else {
            // if basket IS in CheckOut area
            x = MainGamePanel.width - width/2;

            // Start the countdown timer if not already running
            if (!GameManager.count){
                GameManager.count=true;
                GameManager.handler.postDelayed(GameManager.runnable, 0);                               
            }

        }
    } else {

        // Basket is NOT in CheckOut area; stop countdown timer
        GameManager.count=false;
    }

     this.X = x;
 }


 public int getY() {
  return y;
 }
 public void setY(int y) {
        if (y + height/2 > MainGamePanel.height - 80){
            y = MainGamePanel.height - 80 - height/2;
        }


  this.Y = y;
 }


 public boolean isTouched() {
  return touched;
 }

 public void setTouched(boolean touched) {
  this.touched = touched;
 }

 public void draw(Canvas canvas) {
      canvas.drawBitmap(bitmap, X - width/2, Y - height/2, null);
 }

 public void handleActionDown(int eventX, int eventY) {
  if (eventX >= (X - width/ 2) && (eventX <= (X + width/2))) {
   if (eventY >= (Y - height/ 2) && (eventY <= (Y + height/ 2))) {
    // basket touched
    setTouched(true);
   } else {
    setTouched(false);
   }
  } else {
   setTouched(false);
  }

 }
}

回答1:

My bet here is that you are trying to start an activity from an activity that is not fully initialized.

Make sure FirstActivity.onCreate has been called before starting another activity.



回答2:

The error looks like the context provided to the Intent constructor is null.

The code should look more like:

public void startLevelEnd(Context context){
     Intent myIntent = new Intent(context, LevelEndPanel.class);
     context.startActivity(myIntent);
 }

Be sure that you call startLevelEnd from an activity using this call

startLevelEnd(this)

If startLevelEnd is located in the same Activity class that is calling it, simplify it:

public void startLevelEnd(){
     Intent myIntent = new Intent(this, LevelEndPanel.class);
     startActivity(myIntent);
 }


回答3:

I'm fairly sure that you have to use a context for the first parameter in an Intent, and since you have a context as a parameter on your startLevelEnd method, you can try

Intent myIntent = new Intent (context, LevelEndPanel.class);
context.startActivity(myIntent);

I think you're getting the NullPointerException because your class can't see the FirstActivity. But it depends on where the startLevelEnd method is. And since you don't say where it is, try it!