我照着Hello.Android.3rd.Edition.pdf写了一个九宫格游戏,能正常运行,运行后如图所示:然后点击New Game:
弹出Dialog:点击任意难度进入,出现错误:android has stopped unexpectedlyLogcat:12-14 01:16:29.082: D/Sudoku(288): clicked on……012-14 01:16:29.132: D/Sudoku(288): onCreate12-14 01:16:29.263: D/Sudoku(288): onSizeChanged:width 35.555557,height 47.7777812-14 01:16:29.372: D/AndroidRuntime(288): Shutting down VM12-14 01:16:29.372: W/dalvikvm(288): threadid=1: thread exiting with uncaught exception (group=0x4001d800)12-14 01:16:29.412: E/AndroidRuntime(288): FATAL EXCEPTION: main12-14 01:16:29.412: E/AndroidRuntime(288): java.lang.NullPointerException12-14 01:16:29.412: E/AndroidRuntime(288): at org.example.Sudoku.PuzzleView.onDraw(PuzzleView.java:162)12-14 01:16:29.412: E/AndroidRuntime(288): at android.view.View.draw(View.java:6740)12-14 01:16:29.412: E/AndroidRuntime(288): at android.view.ViewGroup.drawChild(ViewGroup.java:1640)12-14 01:16:29.412: E/AndroidRuntime(288): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1367)12-14 01:16:29.412: E/AndroidRuntime(288): at android.view.View.draw(View.java:6743)12-14 01:16:29.412: E/AndroidRuntime(288): at android.widget.FrameLayout.draw(FrameLayout.java:352)12-14 01:16:29.412: E/AndroidRuntime(288): at android.view.ViewGroup.drawChild(ViewGroup.java:1640)12-14 01:16:29.412: E/AndroidRuntime(288): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1367)12-14 01:16:29.412: E/AndroidRuntime(288): at android.view.ViewGroup.drawChild(ViewGroup.java:1638)12-14 01:16:29.412: E/AndroidRuntime(288): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1367)12-14 01:16:29.412: E/AndroidRuntime(288): at android.view.View.draw(View.java:6743)12-14 01:16:29.412: E/AndroidRuntime(288): at android.widget.FrameLayout.draw(FrameLayout.java:352)12-14 01:16:29.412: E/AndroidRuntime(288): at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:1842)12-14 01:16:29.412: E/AndroidRuntime(288): at android.view.ViewRoot.draw(ViewRoot.java:1407)12-14 01:16:29.412: E/AndroidRuntime(288): at android.view.ViewRoot.performTraversals(ViewRoot.java:1163)12-14 01:16:29.412: E/AndroidRuntime(288): at android.view.ViewRoot.handleMessage(ViewRoot.java:1727)12-14 01:16:29.412: E/AndroidRuntime(288): at android.os.Handler.dispatchMessage(Handler.java:99)12-14 01:16:29.412: E/AndroidRuntime(288): at android.os.Looper.loop(Looper.java:123)12-14 01:16:29.412: E/AndroidRuntime(288): at android.app.ActivityThread.main(ActivityThread.java:4627)12-14 01:16:29.412: E/AndroidRuntime(288): at java.lang.reflect.Method.invokeNative(Native Method)12-14 01:16:29.412: E/AndroidRuntime(288): at java.lang.reflect.Method.invoke(Method.java:521)12-14 01:16:29.412: E/AndroidRuntime(288): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)12-14 01:16:29.412: E/AndroidRuntime(288): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)12-14 01:16:29.412: E/AndroidRuntime(288): at dalvik.system.NativeStart.main(Native Method)我前面只知道这种错误是由于没注册Activity造成的,但我全部注册了
请问从这个日志能看出错误在哪吗?有很多个CLASS,我也不知道该帖哪段代码出来 private static final String TAG = "Sudoku";
private void openNewGameDialog() {
new AlertDialog.Builder(this).setTitle(R.string.new_game_title).setItems(R.array.difficulty,new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialoginterface, int i) {
startGame(i);
// TODO Auto-generated method stub
}
}).show();
}
private void startGame(int i) {
Log.d(TAG, "clicked on……"+i);
Intent intent = new Intent(Sudoku.this,Game.class);
intent.putExtra(Game.KEY_DIFFICULTY, i);
startActivity(intent);
//Start game click here
}
}先谢谢各位了,请帮我看看,第一次做就受挫了……
弹出Dialog:点击任意难度进入,出现错误:android has stopped unexpectedlyLogcat:12-14 01:16:29.082: D/Sudoku(288): clicked on……012-14 01:16:29.132: D/Sudoku(288): onCreate12-14 01:16:29.263: D/Sudoku(288): onSizeChanged:width 35.555557,height 47.7777812-14 01:16:29.372: D/AndroidRuntime(288): Shutting down VM12-14 01:16:29.372: W/dalvikvm(288): threadid=1: thread exiting with uncaught exception (group=0x4001d800)12-14 01:16:29.412: E/AndroidRuntime(288): FATAL EXCEPTION: main12-14 01:16:29.412: E/AndroidRuntime(288): java.lang.NullPointerException12-14 01:16:29.412: E/AndroidRuntime(288): at org.example.Sudoku.PuzzleView.onDraw(PuzzleView.java:162)12-14 01:16:29.412: E/AndroidRuntime(288): at android.view.View.draw(View.java:6740)12-14 01:16:29.412: E/AndroidRuntime(288): at android.view.ViewGroup.drawChild(ViewGroup.java:1640)12-14 01:16:29.412: E/AndroidRuntime(288): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1367)12-14 01:16:29.412: E/AndroidRuntime(288): at android.view.View.draw(View.java:6743)12-14 01:16:29.412: E/AndroidRuntime(288): at android.widget.FrameLayout.draw(FrameLayout.java:352)12-14 01:16:29.412: E/AndroidRuntime(288): at android.view.ViewGroup.drawChild(ViewGroup.java:1640)12-14 01:16:29.412: E/AndroidRuntime(288): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1367)12-14 01:16:29.412: E/AndroidRuntime(288): at android.view.ViewGroup.drawChild(ViewGroup.java:1638)12-14 01:16:29.412: E/AndroidRuntime(288): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1367)12-14 01:16:29.412: E/AndroidRuntime(288): at android.view.View.draw(View.java:6743)12-14 01:16:29.412: E/AndroidRuntime(288): at android.widget.FrameLayout.draw(FrameLayout.java:352)12-14 01:16:29.412: E/AndroidRuntime(288): at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:1842)12-14 01:16:29.412: E/AndroidRuntime(288): at android.view.ViewRoot.draw(ViewRoot.java:1407)12-14 01:16:29.412: E/AndroidRuntime(288): at android.view.ViewRoot.performTraversals(ViewRoot.java:1163)12-14 01:16:29.412: E/AndroidRuntime(288): at android.view.ViewRoot.handleMessage(ViewRoot.java:1727)12-14 01:16:29.412: E/AndroidRuntime(288): at android.os.Handler.dispatchMessage(Handler.java:99)12-14 01:16:29.412: E/AndroidRuntime(288): at android.os.Looper.loop(Looper.java:123)12-14 01:16:29.412: E/AndroidRuntime(288): at android.app.ActivityThread.main(ActivityThread.java:4627)12-14 01:16:29.412: E/AndroidRuntime(288): at java.lang.reflect.Method.invokeNative(Native Method)12-14 01:16:29.412: E/AndroidRuntime(288): at java.lang.reflect.Method.invoke(Method.java:521)12-14 01:16:29.412: E/AndroidRuntime(288): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)12-14 01:16:29.412: E/AndroidRuntime(288): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)12-14 01:16:29.412: E/AndroidRuntime(288): at dalvik.system.NativeStart.main(Native Method)我前面只知道这种错误是由于没注册Activity造成的,但我全部注册了
请问从这个日志能看出错误在哪吗?有很多个CLASS,我也不知道该帖哪段代码出来 private static final String TAG = "Sudoku";
private void openNewGameDialog() {
new AlertDialog.Builder(this).setTitle(R.string.new_game_title).setItems(R.array.difficulty,new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialoginterface, int i) {
startGame(i);
// TODO Auto-generated method stub
}
}).show();
}
private void startGame(int i) {
Log.d(TAG, "clicked on……"+i);
Intent intent = new Intent(Sudoku.this,Game.class);
intent.putExtra(Game.KEY_DIFFICULTY, i);
startActivity(intent);
//Start game click here
}
}先谢谢各位了,请帮我看看,第一次做就受挫了……
PuzzleView.java的内容如下:162行已标识package org.example.Sudoku;import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.FontMetrics;
import android.graphics.Paint.Style;
import android.graphics.Rect;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AnimationUtils;public class PuzzleView extends View {
private static final String TAG = "Sudoku";
private final Game game; public PuzzleView(Context context) {
super(context);
this.game = (Game) context;
setFocusable(true);
setFocusableInTouchMode(true);
// TODO Auto-generated constructor stub
} @Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
if (event.getAction() != MotionEvent.ACTION_DOWN)
return super.onTouchEvent(event);
select((int) (event.getX() / width), (int) (event.getY() / height));
game.showKeypadOrError(selX, selY);
Log.d(TAG, "onTouchEvent:x " + selX + ",y " + selY);
return true; } // setSelectTile()方法
public void setSelectTile(int tile) {
if (game.setTileIfValid(selX, selY, tile)) {
invalidate(); // may change hints
} else {
// number is not valid for this hints
Log.d(TAG, "selectedTile : invalid : " + tile);
startAnimation(AnimationUtils.loadAnimation(game, R.anim.shake));
} } @Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
Log.d(TAG, "onKeyDown:keycode = " + keyCode + ",event=" + event); switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_UP:
select(selX, selY - 1);
break;
case KeyEvent.KEYCODE_DPAD_DOWN:
select(selX, selY + 1);
break;
case KeyEvent.KEYCODE_DPAD_LEFT:
select(selX - 1, selY);
break;
case KeyEvent.KEYCODE_DPAD_RIGHT:
select(selX + 1, selY);
break;
case KeyEvent.KEYCODE_0:
case KeyEvent.KEYCODE_SPACE:
setSelectTile(0);
break;
case KeyEvent.KEYCODE_1:
setSelectTile(1);
break;
case KeyEvent.KEYCODE_2:
setSelectTile(2);
break;
case KeyEvent.KEYCODE_3:
setSelectTile(3);
break;
case KeyEvent.KEYCODE_4:
setSelectTile(4);
break;
case KeyEvent.KEYCODE_5:
setSelectTile(5);
break;
case KeyEvent.KEYCODE_6:
setSelectTile(6);
break;
case KeyEvent.KEYCODE_7:
setSelectTile(7);
break;
case KeyEvent.KEYCODE_8:
setSelectTile(8);
break;
case KeyEvent.KEYCODE_9:
setSelectTile(9);
break;
case KeyEvent.KEYCODE_ENTER:
case KeyEvent.KEYCODE_DPAD_CENTER:
game.showKeypadOrError(selX, selY);
break; default:
return super.onKeyDown(keyCode, event);
}
return true;
} // select() 方法
private void select(int x, int y) {
invalidate(selRect);
selX = Math.min(Math.max(x, 0), 8);
selY = Math.min(Math.max(y, 0), 8);
getRect(selX, selY, selRect);
invalidate(selRect);
} @Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
// super.onDraw(canvas);
// Draw the background……
Paint background = new Paint();
background.setColor(getResources().getColor(R.color.puzzle_background));
canvas.drawRect(0, 0, getWidth(), getHeight(), background); // Draw the board……
// Define colors for the grid lines
Paint dark = new Paint();
dark.setColor(getResources().getColor(R.color.puzzle_dark)); Paint hilite = new Paint();
hilite.setColor(getResources().getColor(R.color.puzzle_hilite)); Paint light = new Paint();
light.setColor(getResources().getColor(R.color.puzzle_light)); // Draw the minor grid lines
for (int i = 0; i < 9; i++) {
canvas.drawLine(0, i * height, getWidth(), i * height, light);
canvas.drawLine(0, i * height + 1, getWidth(), i * height + 1,
hilite);
canvas.drawLine(i * width, 0, i * width, getHeight(), light);
canvas.drawLine(i * width + 1, 0, i * width + 1, getHeight(),
hilite); }
// Draw the major grid lines
for (int i = 0; i < 9; i++) {
if (i % 3 != 0)
continue;
canvas.drawLine(0, i * height, getWidth(), i * height, dark);
canvas.drawLine(0, i * height + 1, getWidth(), i * height + 1,
hilite);
canvas.drawLine(i * width, 0, i * width, getHeight(), dark);
canvas.drawLine(i * width + 1, 0, i * width + 1, getHeight(),
hilite);
}
// Draw the numbers……
// Define color and style for numbers
Paint foreground = new Paint(Paint.ANTI_ALIAS_FLAG);
foreground.setColor(getResources().getColor(R.color.puzzle_foreground));
foreground.setStyle(Style.FILL);
foreground.setTextSize(height * 0.75f);
foreground.setTextScaleX(width / height);
foreground.setTextAlign(Paint.Align.CENTER); // Draw the number in the center of the tile
FontMetrics fm = foreground.getFontMetrics();
// Centering in x:use alignment (and X at midpoint)
float x = width / 2;
// Centering in Y : measure ascent/descent first
float y = height / 2 - (fm.ascent + fm.descent) / 2;
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
canvas.drawText(this.game.getTileString(i, j), i * width + x, j
* height + y, foreground);
}
} // Draw the hints……
// Pick a hint color based on #moves left
Paint hint = new Paint();
int c[] = { getResources().getColor(R.color.puzzle_hint_0),
getResources().getColor(R.color.puzzle_hint_1),
getResources().getColor(R.color.puzzle_hint_2), };
Rect r = new Rect();
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
int movesleft = 9 - game.getUsedTiles(i, j).length; //这一行即报错中的162行 --- if (movesleft < c.length) {
getRect(i, j, r);
hint.setColor(c[movesleft]);
canvas.drawRect(r, hint);
}
}
}
// Draw the selection……
Log.d(TAG, "selRect=" + selRect);
Paint selected = new Paint();
selected.setColor(getResources().getColor(R.color.puzzle_selected));
canvas.drawRect(selRect, selected); } private float width;
private float height;
private int selX;
private int selY;
private final Rect selRect = new Rect(); @Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
// TODO Auto-generated method stub
width = w / 9f;
height = h / 9f;
getRect(selX, selY, selRect);
Log.d(TAG, "onSizeChanged:width " + width + ",height " + height);
super.onSizeChanged(w, h, oldw, oldh);
} private void getRect(int x, int y, Rect rect) {
rect.set((int) (x * width), (int) (y * height),
(int) (x * width + width), (int) (y * height + height)); }}
请大家帮我看看,我没找出问题
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.FontMetrics;
import android.graphics.Paint.Style;
import android.graphics.Rect;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AnimationUtils;public class PuzzleView extends View {
private static final String TAG = "Sudoku";
private final Game game; public PuzzleView(Context context) {
super(context);
this.game = (Game) context;
setFocusable(true);
setFocusableInTouchMode(true);
// TODO Auto-generated constructor stub
} @Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
if (event.getAction() != MotionEvent.ACTION_DOWN)
return super.onTouchEvent(event);
select((int) (event.getX() / width), (int) (event.getY() / height));
game.showKeypadOrError(selX, selY);
Log.d(TAG, "onTouchEvent:x " + selX + ",y " + selY);
return true; } // setSelectTile()方法
public void setSelectTile(int tile) {
if (game.setTileIfValid(selX, selY, tile)) {
invalidate(); // may change hints
} else {
// number is not valid for this hints
Log.d(TAG, "selectedTile : invalid : " + tile);
startAnimation(AnimationUtils.loadAnimation(game, R.anim.shake));
} } @Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
Log.d(TAG, "onKeyDown:keycode = " + keyCode + ",event=" + event); switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_UP:
select(selX, selY - 1);
break;
case KeyEvent.KEYCODE_DPAD_DOWN:
select(selX, selY + 1);
break;
case KeyEvent.KEYCODE_DPAD_LEFT:
select(selX - 1, selY);
break;
case KeyEvent.KEYCODE_DPAD_RIGHT:
select(selX + 1, selY);
break;
case KeyEvent.KEYCODE_0:
case KeyEvent.KEYCODE_SPACE:
setSelectTile(0);
break;
case KeyEvent.KEYCODE_1:
setSelectTile(1);
break;
case KeyEvent.KEYCODE_2:
setSelectTile(2);
break;
case KeyEvent.KEYCODE_3:
setSelectTile(3);
break;
case KeyEvent.KEYCODE_4:
setSelectTile(4);
break;
case KeyEvent.KEYCODE_5:
setSelectTile(5);
break;
case KeyEvent.KEYCODE_6:
setSelectTile(6);
break;
case KeyEvent.KEYCODE_7:
setSelectTile(7);
break;
case KeyEvent.KEYCODE_8:
setSelectTile(8);
break;
case KeyEvent.KEYCODE_9:
setSelectTile(9);
break;
case KeyEvent.KEYCODE_ENTER:
case KeyEvent.KEYCODE_DPAD_CENTER:
game.showKeypadOrError(selX, selY);
break; default:
return super.onKeyDown(keyCode, event);
}
return true;
} // select() 方法
private void select(int x, int y) {
invalidate(selRect);
selX = Math.min(Math.max(x, 0), 8);
selY = Math.min(Math.max(y, 0), 8);
getRect(selX, selY, selRect);
invalidate(selRect);
} @Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
// super.onDraw(canvas);
// Draw the background……
Paint background = new Paint();
background.setColor(getResources().getColor(R.color.puzzle_background));
canvas.drawRect(0, 0, getWidth(), getHeight(), background); // Draw the board……
// Define colors for the grid lines
Paint dark = new Paint();
dark.setColor(getResources().getColor(R.color.puzzle_dark)); Paint hilite = new Paint();
hilite.setColor(getResources().getColor(R.color.puzzle_hilite)); Paint light = new Paint();
light.setColor(getResources().getColor(R.color.puzzle_light)); // Draw the minor grid lines
for (int i = 0; i < 9; i++) {
canvas.drawLine(0, i * height, getWidth(), i * height, light);
canvas.drawLine(0, i * height + 1, getWidth(), i * height + 1,
hilite);
canvas.drawLine(i * width, 0, i * width, getHeight(), light);
canvas.drawLine(i * width + 1, 0, i * width + 1, getHeight(),
hilite); }
// Draw the major grid lines
for (int i = 0; i < 9; i++) {
if (i % 3 != 0)
continue;
canvas.drawLine(0, i * height, getWidth(), i * height, dark);
canvas.drawLine(0, i * height + 1, getWidth(), i * height + 1,
hilite);
canvas.drawLine(i * width, 0, i * width, getHeight(), dark);
canvas.drawLine(i * width + 1, 0, i * width + 1, getHeight(),
hilite);
}
// Draw the numbers……
// Define color and style for numbers
Paint foreground = new Paint(Paint.ANTI_ALIAS_FLAG);
foreground.setColor(getResources().getColor(R.color.puzzle_foreground));
foreground.setStyle(Style.FILL);
foreground.setTextSize(height * 0.75f);
foreground.setTextScaleX(width / height);
foreground.setTextAlign(Paint.Align.CENTER); // Draw the number in the center of the tile
FontMetrics fm = foreground.getFontMetrics();
// Centering in x:use alignment (and X at midpoint)
float x = width / 2;
// Centering in Y : measure ascent/descent first
float y = height / 2 - (fm.ascent + fm.descent) / 2;
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
canvas.drawText(this.game.getTileString(i, j), i * width + x, j
* height + y, foreground);
}
} // Draw the hints……
// Pick a hint color based on #moves left
Paint hint = new Paint();
int c[] = { getResources().getColor(R.color.puzzle_hint_0),
getResources().getColor(R.color.puzzle_hint_1),
getResources().getColor(R.color.puzzle_hint_2), };
Rect r = new Rect();
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
int movesleft = 9 - game.getUsedTiles(i, j).length; //这一行即报错中的162行 ---
if (movesleft < c.length) {
getRect(i, j, r);
hint.setColor(c[movesleft]);
canvas.drawRect(r, hint);
}
}
}
// Draw the selection……
Log.d(TAG, "selRect=" + selRect);
Paint selected = new Paint();
selected.setColor(getResources().getColor(R.color.puzzle_selected));
canvas.drawRect(selRect, selected); } private float width;
private float height;
private int selX;
private int selY;
private final Rect selRect = new Rect(); @Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
// TODO Auto-generated method stub
width = w / 9f;
height = h / 9f;
getRect(selX, selY, selRect);
Log.d(TAG, "onSizeChanged:width " + width + ",height " + height);
super.onSizeChanged(w, h, oldw, oldh);
} private void getRect(int x, int y, Rect rect) {
rect.set((int) (x * width), (int) (y * height),
(int) (x * width + width), (int) (y * height + height)); }}
int movesleft = 9 - game.getUsedTiles(i, j).length;这行会出现空指针的唯一情况,就是game.getUsedTitles(i,j)返回的是Null,null调用.length当然就会出现空指针异常,因为你没有给出Game类的代码和getUsedTitles(i,j),所以也不好跟你做什么分析,还是你自己多调试调试吧
int movesleft = 9 - game.getUsedTiles(i, j).length;
……
}算是临时解决了问题,不知道有没有什么隐患