你好,当应用程序运行时一切正常,但当我尝试点击保存时,我得到一个错误。首先它有外部存储权限和错误。我解决了这个问题,但现在我收到了以下错误。
有人可以查看我的代码,看看你能否看到我错过的内容?
它表示NullPointerException
,但它指向的行在代码中没有null
个点。
代码:
package com.androidbook.pettracker3;
import android.app.LoaderManager;
import android.content.ContentValues;
import android.content.Context;
import android.content.CursorLoader;
import android.content.Intent;
import android.content.Loader;
import android.content.res.TypedArray;
import android.database.Cursor;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.CursorAdapter;
import android.widget.EditText;
import android.widget.FilterQueryProvider;
import android.widget.Gallery;
import android.widget.ImageView;
import android.widget.RadioGroup.LayoutParams;
import android.widget.SimpleCursorAdapter;
import com.androidbook.pettracker3.PetTrackerDatabase.PetType;
import com.androidbook.pettracker3.PetTrackerDatabase.Pets;
public class PetTrackerEntryActivity extends PetTrackerActivity implements
LoaderManager.LoaderCallbacks<Cursor> {
private static final int GALLERY_CURSOR_LOADER_ID = 0x1001;
private static final String GALLERY_CURSOR_URI_ARG = "GALLERY_CURSOR_URI_ARG";
protected Cursor mCursorAutoComplete;
protected Cursor mThumbnailImagesCursor;
private Gallery imagePickerGallery;
private ImageUriAdapter mGalleryAdapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// use this to note how the setImageURI method is bad
/*StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectAll().penaltyFlashScreen().penaltyLog().build());
*/
setContentView(R.layout.petentry);
// Fill our Gallery from pictures available on the SD Card
setGalleryAdapter();
// Fill AutoComplete word list from database
fillAutoComplete();
imagePickerGallery = (Gallery) findViewById(R.id.GalleryOfPics);
// Handle Save Button
final Button savePet = (Button) findViewById(R.id.ButtonSave);
savePet.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
final EditText petName = (EditText) findViewById(R.id.EditTextName);
final EditText petType = (EditText) findViewById(R.id.EditTextSpecies);
long imageId = PetRecord.INVALID_PET_IMAGE_ID;
ImageView selectedImageView = (ImageView) imagePickerGallery
.getSelectedView();
Uri imageUri = (Uri) selectedImageView.getTag();
String imageUriString = imageUri.toString();
String strPetType = petType.getText().toString().toLowerCase();
String strPetName = petName.getText().toString();
PetRecord newRecord = new PetRecord(strPetName, strPetType,
imageUriString, imageId, PetRecord.INVALID_PET_ID);
addPetRecord(newRecord);
// reset form
petName.setText(null);
petType.setText(null);
}
});
// Handle Go to List button
final Button gotoList = (Button) findViewById(R.id.ButtonShowPets);
gotoList.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Go to other activity that displays pet list
Intent intent = new Intent(PetTrackerEntryActivity.this,
PetTrackerListActivity.class);
startActivity(intent);
}
});
}
//
private void setGalleryAdapter() {
// The base URI for SD Card content
Uri thumbnailUri = MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI;
mGalleryAdapter = new ImageUriAdapter(this, null, false, thumbnailUri);
// Assign the adapter to our Gallery to display the images
final Gallery pictureGal = (Gallery) findViewById(R.id.GalleryOfPics);
pictureGal.setAdapter(mGalleryAdapter);
// use a loader to get the cursor and assign it to this adapter
Bundle args = new Bundle();
args.putString(GALLERY_CURSOR_URI_ARG, thumbnailUri.toString());
getLoaderManager().initLoader(GALLERY_CURSOR_LOADER_ID, args, this);
}
private void fillAutoComplete() {
mCursorAutoComplete = mDB.query(PetType.PETTYPE_TABLE_NAME,
new String[] { PetType.PET_TYPE_NAME, PetType._ID }, null,
null, null, null, PetType.DEFAULT_SORT_ORDER);
startManagingCursor(mCursorAutoComplete);
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
android.R.layout.simple_dropdown_item_1line,
mCursorAutoComplete, new String[] { PetType.PET_TYPE_NAME },
new int[] { android.R.id.text1 });
// I just want the text splatted into the edittext, not the textview
// object
// so I implemented a CursorToStringConverter and a FilterQueryProvider
// CursorToStringConverter - controls what "value" is returned when an
// AutoText option is chosen
// in this case, the text itself, not the id to the text
// FilterQueryProvider - interface to get control over the filtering
// process, which we implement a custom matching function
adapter.setCursorToStringConverter(new MyCursorToStringConverter());
adapter.setFilterQueryProvider(new MyFilterQueryProvider());
AutoCompleteTextView text = (AutoCompleteTextView) findViewById(R.id.EditTextSpecies);
text.setAdapter(adapter);
}
// This controls what column to place in the edittext when selected. The
// default textview.tostring, not helpful
class MyCursorToStringConverter implements
SimpleCursorAdapter.CursorToStringConverter {
public CharSequence convertToString(Cursor cursor) {
return cursor.getString(cursor
.getColumnIndex(PetType.PET_TYPE_NAME));
}
}
// Our custom filter finds all substring matches, not just the beginning of
// the string, just for kicks
// There's a bit of a workaround here, since this function does not handle
// Cursor refreshing appropriately
class MyFilterQueryProvider implements FilterQueryProvider {
public Cursor runQuery(CharSequence constraint) {
if ((constraint != null) && (mCursorAutoComplete != null)) {
String strWhere = PetType.PET_TYPE_NAME + " LIKE ?";
stopManagingCursor(mCursorAutoComplete);
mCursorAutoComplete = mDB
.query(PetType.PETTYPE_TABLE_NAME, new String[] {
PetType.PET_TYPE_NAME, PetType._ID }, strWhere,
new String[] { "%" + constraint.toString()
+ "%" }, null, null,
PetType.DEFAULT_SORT_ORDER);
startManagingCursor(mCursorAutoComplete);
}
return mCursorAutoComplete;
}
}
// Add appropriate records to the database (Pet and Pet_Type)
private void addPetRecord(PetRecord newRecord) {
// Save new records, since we're saving multiple records, let's do a
// transaction so it's all or nothing
mDB.beginTransaction();
try {
// check if species type exists already
long rowPetTypeId = 0;
// SQL Query -> "select * from table_pettype where
// PetType.pettype_name='string'
SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
queryBuilder.setTables(PetType.PETTYPE_TABLE_NAME);
queryBuilder.appendWhere(PetType.PET_TYPE_NAME + "='"
+ newRecord.getPetType() + "'");
// run the query since it's all ready to go
Cursor c = queryBuilder.query(mDB, null, null, null, null, null,
null);
if (c.getCount() == 0) {
// add the new type to our list
ContentValues typeRecordToAdd = new ContentValues();
typeRecordToAdd.put(PetType.PET_TYPE_NAME,
newRecord.getPetType());
rowPetTypeId = mDB.insert(PetType.PETTYPE_TABLE_NAME,
PetType.PET_TYPE_NAME, typeRecordToAdd);
} else {
// Type already exists, grab the row id to refer to below
c.moveToFirst();
rowPetTypeId = c.getLong(c.getColumnIndex(PetType._ID));
}
c.close();
// Always insert new pet records, even if the names clash
ContentValues petRecordToAdd = new ContentValues();
petRecordToAdd.put(Pets.PET_NAME, newRecord.getPetName());
petRecordToAdd.put(Pets.PET_TYPE_ID, rowPetTypeId);
petRecordToAdd.put(Pets.PET_IMAGE_URI,
newRecord.getPetImageUriPath());
petRecordToAdd.put(Pets.PET_IMAGE_ID, newRecord.getPetImageId());
mDB.insert(Pets.PETS_TABLE_NAME, Pets.PET_NAME, petRecordToAdd);
mDB.setTransactionSuccessful();
} finally {
mDB.endTransaction();
}
}
public class ImageUriAdapter extends CursorAdapter {
private int colIndexMediaId;
private final Uri baseUri;
private final int mGalleryItemBackground;
public ImageUriAdapter(Context context, Cursor c, boolean autoRequery,
Uri baseUri) {
super(context, c, autoRequery);
if (c != null) {
colIndexMediaId = c
.getColumnIndex(MediaStore.Images.Thumbnails._ID);
}
this.baseUri = baseUri;
TypedArray a = obtainStyledAttributes(R.styleable.default_gallery);
mGalleryItemBackground = a.getResourceId(
R.styleable.default_gallery_android_galleryItemBackground, 0);
a.recycle();
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
long id = cursor.getLong(colIndexMediaId);
// TODO: this should be done on a background thread; it blocks
Uri imageUri = Uri.withAppendedPath(baseUri, String.valueOf(id));
((ImageView) view).setImageURI(imageUri);
view.setTag(imageUri);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
ImageView imageView = new ImageView(context);
long id = cursor.getLong(colIndexMediaId);
// TODO: this should be done on a background thread; it blocks
Uri imageUri = Uri.withAppendedPath(baseUri, String.valueOf(id));
imageView.setImageURI(imageUri);
// Constrain the images so they all look the same size/ratio
imageView.setLayoutParams(new Gallery.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
imageView.setTag(imageUri);
imageView.setBackgroundResource(mGalleryItemBackground);
return imageView;
}
@Override
public Cursor swapCursor(Cursor newCursor) {
if (newCursor != null) {
colIndexMediaId = newCursor
.getColumnIndex(MediaStore.Images.Thumbnails._ID);
}
return super.swapCursor(newCursor);
}
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
switch (id) {
case GALLERY_CURSOR_LOADER_ID:
// An array specifying which columns to return.
String[] projection = new String[] { MediaStore.Images.Thumbnails._ID };
// The base URI for SD Card content
Uri thumbnailUri = Uri
.parse(args.getString(GALLERY_CURSOR_URI_ARG));
// thumbnails of all external images in the media store
// Best way to retrieve a cursor; performs operation on a background
// thread
CursorLoader loader = new CursorLoader(this, thumbnailUri,
projection, null, null,
MediaStore.Images.Thumbnails.DEFAULT_SORT_ORDER
//+ " limit 50"
);
return loader;
}
return null;
}
@Override
public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) {
switch (cursorLoader.getId()) {
case GALLERY_CURSOR_LOADER_ID:
mGalleryAdapter.swapCursor(cursor);
break;
}
}
@Override
public void onLoaderReset(Loader<Cursor> cursorLoader) {
switch (cursorLoader.getId()) {
case GALLERY_CURSOR_LOADER_ID:
mGalleryAdapter.swapCursor(null);
break;
}
}
错误消息
D/dalvikvm: Not late-enabling CheckJNI (already on)
04-07 15:25:41.172 2212-2212/? E/Trace: error opening trace file: No such file or directory (2)
04-07 15:25:41.172 2212-2212/com.androidbook.pettracker3 W/ActivityThread: Application com.androidbook.pettracker3 is waiting for the debugger on port 8100...
04-07 15:25:41.182 2212-2212/com.androidbook.pettracker3 I/System.out: Sending WAIT chunk
04-07 15:25:41.842 2212-2219/com.androidbook.pettracker3 I/dalvikvm: Debugger is active
04-07 15:25:42.012 2212-2212/com.androidbook.pettracker3 I/System.out: Debugger has connected
04-07 15:25:42.012 2212-2212/com.androidbook.pettracker3 I/System.out: waiting for debugger to settle...
04-07 15:25:42.212 2212-2212/com.androidbook.pettracker3 I/System.out: waiting for debugger to settle...
04-07 15:25:42.422 2212-2212/com.androidbook.pettracker3 I/System.out: waiting for debugger to settle...
04-07 15:25:42.632 2212-2212/com.androidbook.pettracker3 I/System.out: waiting for debugger to settle...
04-07 15:25:42.842 2212-2212/com.androidbook.pettracker3 I/System.out: waiting for debugger to settle...
04-07 15:25:43.052 2212-2212/com.androidbook.pettracker3 I/System.out: waiting for debugger to settle...
04-07 15:25:43.262 2212-2212/com.androidbook.pettracker3 I/System.out: waiting for debugger to settle...
04-07 15:25:43.472 2212-2212/com.androidbook.pettracker3 I/System.out: waiting for debugger to settle...
04-07 15:25:43.682 2212-2212/com.androidbook.pettracker3 I/System.out: waiting for debugger to settle...
04-07 15:25:43.892 2212-2212/com.androidbook.pettracker3 I/System.out: debugger has settled (1352)
04-07 15:25:43.922 2212-2217/com.androidbook.pettracker3 D/dalvikvm: GC_CONCURRENT freed 131K, 7% free 2675K/2864K, paused 7ms+0ms, total 9ms
04-07 15:25:43.942 2212-2217/com.androidbook.pettracker3 D/dalvikvm: GC_CONCURRENT freed 117K, 9% free 2958K/3216K, paused 3ms+0ms, total 5ms
04-07 15:25:43.972 2212-2217/com.androidbook.pettracker3 D/dalvikvm: GC_CONCURRENT freed 129K, 8% free 3228K/3480K, paused 9ms+1ms, total 12ms
04-07 15:25:44.041 2212-2212/com.androidbook.pettracker3 D/libEGL: loaded /system/lib/egl/libEGL_emulation.so
04-07 15:25:44.041 2212-2212/com.androidbook.pettracker3 D/libEGL: loaded /system/lib/egl/libGLESv1_CM_emulation.so
04-07 15:25:44.041 2212-2212/com.androidbook.pettracker3 D/libEGL: loaded /system/lib/egl/libGLESv2_emulation.so
04-07 15:25:44.092 2212-2212/com.androidbook.pettracker3 W/EGL_emulation: eglSurfaceAttrib not implemented
04-07 15:25:44.092 2212-2212/com.androidbook.pettracker3 D/OpenGLRenderer: Enabling debug mode 0
04-07 15:26:22.622 2212-2212/com.androidbook.pettracker3 D/AndroidRuntime: Shutting down VM
04-07 15:26:22.622 2212-2212/com.androidbook.pettracker3 W/dalvikvm: threadid=1: thread exiting with uncaught exception (group=0xb2d17908)
04-07 15:26:22.622 2212-2212/com.androidbook.pettracker3 E/AndroidRuntime:
FATAL EXCEPTION: main java.lang.NullPointerException
at com.androidbook.pettracker3.PetTrackerEntryActivity$1.onClick(PetTrackerEntryAct ivity.java:70)
at android.view.View.performClick(View.java:4204)
at android.view.View$PerformClick.run(View.java:17355)
at android.os.Handler.handleCallback(Handler.java:725)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5041)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
at dalvik.system.NativeStart.main(Native Method)
04-07 15:26:27.422 2212-2212/? I/Process: Sending signal. PID: 2212 SIG: 9
petentry.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
style="@android:style/TextAppearance.Large"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/enter_data"
android:textColor="#0f0" />
<TableLayout
android:id="@+id/TableLayout01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:shrinkColumns="*"
android:stretchColumns="1" >
<TableRow
android:id="@+id/TableRow01"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Pet Name:" >
</TextView>
<EditText
android:id="@+id/EditTextName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inputType="textCapWords" >
</EditText>
</TableRow>
<TableRow
android:id="@+id/TableRow02"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Pet Species:" >
</TextView>
<AutoCompleteTextView
android:id="@+id/EditTextSpecies"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
</AutoCompleteTextView>
</TableRow>
<TableRow
android:id="@+id/TableRow03"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Choose Pet Picture:" >
</TextView>
</TableRow>
<TableRow
android:id="@+id/TableRow04"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<Gallery
android:id="@+id/GalleryOfPics"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_span="2" >
</Gallery>
</TableRow>
</TableLayout>
<Button
android:id="@+id/ButtonSave"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/save" >
</Button>
<Button
android:id="@+id/ButtonShowPets"
style="@android:style/TextAppearance.Large"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Show All Pets"
android:textColor="#0f0" >
</Button>
</LinearLayout>