**ISSUE:**
我检查了模拟器数据库正在创建并且应用程序运行正常。但是,当我在此应用程序运行时单击真实 android 设备上的提交按钮时,它会强制关闭。请朋友们帮帮我。代码如下:
这是 main.xml 文件,用户在其中输入信息并单击提交,之后他通过 gui 输入的值应保存到数据库中的相应表中。
**Main.xml**
--------
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<EditText
android:id="@+id/editxt_mbno"
android:textColorHint="@color/BurlyWood"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/txt_mbno"
android:layout_alignBottom="@+id/txt_mbno"
android:layout_marginLeft="40dp"
android:layout_toRightOf="@+id/txt_mbno"
android:ems="10"
android:hint="@string/edit_mbno" >
<requestFocus />
</EditText>
<TextView
android:id="@+id/txt_narrative"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/txt_welcome"
android:layout_centerHorizontal="true"
android:text="@string/narrative"
android:textColor="@color/LimeGreen"
android:textSize="16sp" />
<TextView
android:id="@+id/txt_welcome"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="15dp"
android:text="@string/welcome"
android:textColor="@color/red"
android:textSize="28sp" />
<EditText
android:id="@+id/editxt_cloudid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/sbmt_btn"
android:layout_alignLeft="@+id/editxt_empid"
android:ems="10"
android:hint="@string/edit_cloudid"
android:textColorHint="@color/BurlyWood" />
<EditText
android:id="@+id/editxt_empid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/editxt_cloudid"
android:layout_alignLeft="@+id/editxt_clientid"
android:ems="10"
android:hint="@string/edit_empid"
android:textColorHint="@color/BurlyWood" />
<EditText
android:id="@+id/editxt_clientid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/editxt_empid"
android:layout_alignLeft="@+id/editxt_mbno"
android:ems="10"
android:hint="@string/edit_clientid"
android:textColorHint="@color/BurlyWood" />
<TextView
android:id="@+id/txt_employeeid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/txt_narrative"
android:layout_alignTop="@+id/editxt_empid"
android:layout_marginTop="14dp"
android:text="@string/employee_id"
android:textColor="@color/Chocolate" />
<TextView
android:id="@+id/txt_clientid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/editxt_clientid"
android:layout_alignBottom="@+id/editxt_clientid"
android:layout_alignLeft="@+id/txt_employeeid"
android:text="@string/client_id"
android:textColor="@color/Chocolate" />
<TextView
android:id="@+id/txt_mbno"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/editxt_clientid"
android:layout_alignLeft="@+id/txt_clientid"
android:layout_marginBottom="26dp"
android:text="@string/mobile_no"
android:textColor="@color/Chocolate" />
<Button
android:id="@+id/sbmt_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_toRightOf="@+id/txt_mbno"
android:background="@drawable/draw"
android:text="@string/btn_txt" />
<TextView
android:id="@+id/txt_cloudid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/editxt_cloudid"
android:layout_alignBottom="@+id/editxt_cloudid"
android:layout_alignLeft="@+id/txt_employeeid"
android:text="@string/cloud_id"
android:textColor="@color/Chocolate" />
</RelativeLayout>
**
这是我在代码中用作数据对象的类。它基本上包含 getter 和 setter 方法。
Tracking.java
-------------
**
package nice.work.attendance_tracking;
public class Tracking {
private Long mob_no;
private String client_id;
private String emp_id;
private String cloud_id;
// adding 5 new fields for testing
private String datetime;
private Integer event_id;
private String event_name;
private String remarks;
private String spinner_txt;
public Long getmobno() {
return mob_no;
}
public void setmobno(long mob_no) {
this.mob_no = mob_no;
}
public String getclientid() {
return client_id;
}
public void setclientid(String client_id) {
this.client_id = client_id;
}
public String getempid() {
return emp_id;
}
public void setempid(String emp_id) {
this.emp_id = emp_id;
}
public String getcloudid() {
return cloud_id;
}
public void setcloudid(String cloud_id) {
this.cloud_id = cloud_id;
}
// added new methods for testing
public String getdatetime() {
return datetime;
}
public void setdatetime(String datetime) {
this.datetime = datetime;
}
public Integer geteventid() {
return event_id;
}
public void seteventid(int event_id) {
this.event_id = event_id;
}
public String geteventname() {
return event_name;
}
public void seteventname(String event_name) {
this.event_name = event_name;
}
public String getremarks() {
return remarks;
}
public void setremarks(String remarks) {
this.remarks = remarks;
}
public String getspinnertxt() {
return spinner_txt;
}
public void setspinnertxt(String spinner_txt) {
this.spinner_txt = spinner_txt;
}
}
**
这是主活动文件,也是我的应用程序调用的第一个活动。
MainActivity.java
-----------------
**
package nice.work.attendance_tracking;
import java.util.ArrayList;
import android.os.Bundle;
import android.app.Activity;
import android.content.ContentValues;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends Activity implements OnClickListener{
private EditText editmobno;
private EditText editclientid;
private EditText editempid;
private EditText editcloudid;
private Button submit;
private ArrayList<Tracking> TrackingObjArrayList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editmobno=(EditText)findViewById(R.id.editxt_mbno);
editclientid=(EditText)findViewById(R.id.editxt_clientid);
editempid=(EditText)findViewById(R.id.editxt_empid);
editcloudid=(EditText) findViewById(R.id.editxt_cloudid);
submit=(Button)findViewById(R.id.sbmt_btn);
submit.setOnClickListener(this);
TrackingObjArrayList = new ArrayList<Tracking>();
}
public void onClick(View v)
{
if(v.getId()==R.id.sbmt_btn)
{
// Get the values provided by the user via the UI
Long providedmobno = Long.parseLong(editmobno.getText().toString());
String providedclientid = editclientid.getText().toString();
String providedempid = editempid.getText().toString();
String providedcloudid = editcloudid.getText().toString();
// Pass above values to the setter methods in POJO class
Tracking TrackingObj = new Tracking();
TrackingObj.setmobno(providedmobno);
TrackingObj.setclientid(providedclientid);
TrackingObj.setempid(providedempid);
TrackingObj.setcloudid(providedcloudid);
// Add an undergraduate with his all details to a ArrayList
TrackingObjArrayList.add(TrackingObj);
// Inserting tracking details to the database is doing in a separate method
insertTracking(TrackingObj);
// Release from the existing UI and go back to the previous UI
finish();
Intent i = new Intent(MainActivity.this,Transaction.class);
startActivity(i);
}
}
public void insertTracking(Tracking paraTrackingObj){
// First we have to open our DbHelper class by creating a new object of that
AssetDatabaseOpenHelper androidOpenDbHelperObj = new AssetDatabaseOpenHelper(this);
// Then we need to get a writable SQLite database, because we are going to insert some values
// SQLiteDatabase has methods to create, delete, execute SQL commands, and perform other common database management tasks.
SQLiteDatabase sqliteDatabase = androidOpenDbHelperObj.getWritableDatabase();
// ContentValues class is used to store a set of values that the ContentResolver can process.
ContentValues contentValues = new ContentValues();
// Get values from the Tracking class and passing them to the ContentValues class
contentValues.put(AssetDatabaseOpenHelper.COLUMN_NAME_MOB_NO, paraTrackingObj.getmobno());
contentValues.put(AssetDatabaseOpenHelper.COLUMN_NAME_CLIENT_ID, paraTrackingObj.getclientid());
contentValues.put(AssetDatabaseOpenHelper.COLUMN_NAME_EMPLOYEE_ID, paraTrackingObj.getempid());
contentValues.put(AssetDatabaseOpenHelper.COLUMN_NAME_CLOUD_ID, paraTrackingObj.getcloudid());
// Now we can insert the data in to relevant table
// I am going pass the id value, which is going to change because of our insert method, to a long variable to show in Toast
long affectedColumnId = sqliteDatabase.insert(AssetDatabaseOpenHelper.TABLE_NAME, null, contentValues);
// It is a good practice to close the database connections after you have done with it
sqliteDatabase.close();
// I am not going to do the retrieve part in this post. So this is just a notification for satisfaction ;-)
Toast.makeText(this, "Values inserted column ID is :" + affectedColumnId, Toast.LENGTH_SHORT).show();
}
}
**
这是我的数据库活动文件,其中包含将在后端完成的所有数据库代码。
AssetDatabaseOpenHelper.java
----------------------------
**
package nice.work.attendance_tracking;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.provider.BaseColumns;
public class AssetDatabaseOpenHelper extends SQLiteOpenHelper {
private static final String DB_NAME = "Attendance.sqlite";
public static final int DB_VERSION = 1;
// Labels table name
private static final String TABLE_LABELS = "Event";
// Labels Table Columns names
// private static final String KEY_ID = "Event_id";
// private static final String KEY_NAME = "Event_Name";
// Table attributes
public static final String TABLE_NAME = "Param_Value";
public static final String COLUMN_NAME_MOB_NO = "Mob_no";
public static final String COLUMN_NAME_CLIENT_ID = "Client_id";
public static final String COLUMN_NAME_EMPLOYEE_ID = "Emp_id";
public static final String COLUMN_NAME_CLOUD_ID = "Cloud_id";
// added additional fields for testing purpose
public static final String TABLE_NAMES = "Transaction_Table";
public static final String COLUMN_NAME_DATETIME = "DateTime";
public static final String COLUMN_NAME_EVENT_ID = "Event_id";
public static final String COLUMN_NAME_EVENT_NAME = "Event_name";
public static final String COLUMN_NAME_REMARKS = "Remarks";
private Context context;
// public AssetDatabaseOpenHelper(Context context) {
// this.context = context;
//}
public AssetDatabaseOpenHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
public SQLiteDatabase openDatabase() {
File dbFile = context.getDatabasePath(DB_NAME);
if (!dbFile.exists()) {
try {
copyDatabase(dbFile);
} catch (IOException e) {
throw new RuntimeException("Error creating source database", e);
}
}
return SQLiteDatabase.openDatabase(dbFile.getPath(), null, SQLiteDatabase.OPEN_READONLY);
}
private void copyDatabase(File dbFile) throws IOException {
InputStream is = context.getAssets().open(DB_NAME);
OutputStream os = new FileOutputStream(dbFile);
byte[] buffer = new byte[1024];
while (is.read(buffer) > 0) {
os.write(buffer);
}
os.flush();
os.close();
is.close();
}
public void onCreate(SQLiteDatabase db) {
// We need to check whether table that we are going to create is already exists.
//Because this method get executed every time we created an object of this class.
//"create table if not exists TABLE_NAME ( BaseColumns._ID integer primary key autoincrement, FIRST_COLUMN_NAME text not null, SECOND_COLUMN_NAME integer not null);"
String sqlQueryToCreateTrackingTable = "create table if not exists " + TABLE_NAME + " ( " + BaseColumns._ID + " integer primary key autoincrement, "
+ COLUMN_NAME_MOB_NO + " integer not null, "
+ COLUMN_NAME_CLIENT_ID + " text not null, "
+ COLUMN_NAME_EMPLOYEE_ID + " text not null, "
+ COLUMN_NAME_CLOUD_ID + " integer not null);";
// Execute a single SQL statement that is NOT a SELECT or any other SQL statement that returns data.
db.execSQL(sqlQueryToCreateTrackingTable);
}
// onUpgrade method is use when we need to upgrade the database in to a new version
//As an example, the first release of the app contains DB_VERSION = 1
//Then with the second release of the same app contains DB_VERSION = 2
//where you may have add some new tables or alter the existing ones
//Then we need check and do relevant action to keep our pass data and move with the next structure
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if(oldVersion == 1 && newVersion == 2){
// Upgrade the database
}
}
/**
* Getting all labels
* returns list of labels
* */
public List<String> getAllLabels(){
List<String> labels = new ArrayList<String>();
// Select All Query
String selectQuery = "SELECT * FROM " + TABLE_LABELS;
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
labels.add(cursor.getString(1));
} while (cursor.moveToNext());
}
// closing connection
cursor.close();
db.close();
// returning lables
return labels;
}
}
LOGCAT AFTER I RAN APP ON DEVICE AND IT FORCE CLOSED
11-12 11:55:49.880: E/AndroidRuntime(9972): FATAL EXCEPTION: main
11-12 11:55:49.880: E/AndroidRuntime(9972): java.lang.RuntimeException: Unable to start activity ComponentInfo{nice.work.attendance_tracking/nice.work.attendance_tracking.Transaction}: android.database.sqlite.SQLiteException: no such table: Event (code 1): , while compiling: SELECT * FROM Event
11-12 11:55:49.880: E/AndroidRuntime(9972): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2306)
11-12 11:55:49.880: E/AndroidRuntime(9972): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2358)
11-12 11:55:49.880: E/AndroidRuntime(9972): at android.app.ActivityThread.access$600(ActivityThread.java:156)
11-12 11:55:49.880: E/AndroidRuntime(9972): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1340)
11-12 11:55:49.880: E/AndroidRuntime(9972): at android.os.Handler.dispatchMessage(Handler.java:99)
11-12 11:55:49.880: E/AndroidRuntime(9972): at android.os.Looper.loop(Looper.java:153)
11-12 11:55:49.880: E/AndroidRuntime(9972): at android.app.ActivityThread.main(ActivityThread.java:5297)
11-12 11:55:49.880: E/AndroidRuntime(9972): at java.lang.reflect.Method.invokeNative(Native Method)
11-12 11:55:49.880: E/AndroidRuntime(9972): at java.lang.reflect.Method.invoke(Method.java:511)
11-12 11:55:49.880: E/AndroidRuntime(9972): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:833)
11-12 11:55:49.880: E/AndroidRuntime(9972): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
11-12 11:55:49.880: E/AndroidRuntime(9972): at dalvik.system.NativeStart.main(Native Method)
11-12 11:55:49.880: E/AndroidRuntime(9972): Caused by: android.database.sqlite.SQLiteException: no such table: Event (code 1): , while compiling: SELECT * FROM Event
11-12 11:55:49.880: E/AndroidRuntime(9972): at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
11-12 11:55:49.880: E/AndroidRuntime(9972): at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:886)
11-12 11:55:49.880: E/AndroidRuntime(9972): at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:497)
11-12 11:55:49.880: E/AndroidRuntime(9972): at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588)
11-12 11:55:49.880: E/AndroidRuntime(9972): at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:58)
11-12 11:55:49.880: E/AndroidRuntime(9972): at android.database.sqlite.SQLiteQuery.<init>(SQLiteQuery.java:37)
11-12 11:55:49.880: E/AndroidRuntime(9972): at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:44)
11-12 11:55:49.880: E/AndroidRuntime(9972): at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1314)
11-12 11:55:49.880: E/AndroidRuntime(9972): at android.database.sqlite.SQLiteDatabase.rawQuery(SQLiteDatabase.java:1253)
11-12 11:55:49.880: E/AndroidRuntime(9972): at nice.work.attendance_tracking.AssetDatabaseOpenHelper.getAllLabels(AssetDatabaseOpenHelper.java:116)
11-12 11:55:49.880: E/AndroidRuntime(9972): at nice.work.attendance_tracking.Transaction.loadSpinnerData(Transaction.java:57)
11-12 11:55:49.880: E/AndroidRuntime(9972): at nice.work.attendance_tracking.Transaction.onCreate(Transaction.java:43)
11-12 11:55:49.880: E/AndroidRuntime(9972): at android.app.Activity.performCreate(Activity.java:5122)
11-12 11:55:49.880: E/AndroidRuntime(9972): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1081)
11-12 11:55:49.880: E/AndroidRuntime(9972): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2270)
11-12 11:55:49.880: E/AndroidRuntime(9972): ... 11 more
数据库链接: http ://dh.st/JKy
我可以看到通过 eclipse ddms 透视图使用模拟器时创建了数据库。但是当我使用 adb shell ls /data/data/nice.work.attendance_tracking/databases/ 时,即使我的应用程序在模拟器中运行,我也总是让设备脱机。
另外,我需要知道我的数据库代码中是否有任何问题。但是当我在模拟器上运行应用程序时,值会保存到我的数据库中。当应用程序强制在真实设备上单击提交时关闭(之后应该将值保存到数据库表)。