我已阅读了数千页,尚未找到解决方案。我在Android开发方面相对较新,这是我第一次在移动设备上部署任何类型的应用程序而我的问题是应用程序在我的模拟器上运行完美无缺,但在我的设备上它在启动时崩溃。我有点指向错误,因为与我使用应用程序打包的数据库访问数据有关。
基本上,我的第一个活动是调用一个函数来从数据库中检索机场代码。它到达我的DBContext文件中的函数并返回错误:
0java.lang.RuntimeException: Unable to start activity ComponentInfo{com.maziz.POS/com.maziz.POS.Login}: java.lang.NullPointerException
1at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1647)
2at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1663)
3at android.app.ActivityThread.access$1500(ActivityThread.java:117)
4at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931)
5at android.os.Handler.dispatchMessage(Handler.java:99)
6at android.os.Looper.loop(Looper.java:130)
7at android.app.ActivityThread.main(ActivityThread.java:3683)
8at java.lang.reflect.Method.invokeNative(Native Method)
9at java.lang.reflect.Method.invoke(Method.java:507)
10at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
11at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
12at dalvik.system.NativeStart.main(Native Method) Caused by: java.lang.NullPointerException
13at com.maziz.POS.POSContext.getAirportCodes(POSContext.java:178)
14at com.maziz.POS.Login.onCreate(Login.java:29)
15at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
16at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1611)
17... 11 more
FirstActivity:Login.java
package com.maziz.POS;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.bugsense.trace.BugSenseHandler;
public class Login extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Creates instance of all Global Vars
// GlobalVars gv = (GlobalVars) getApplicationContext();
BugSenseHandler.setup(this, "00728e23");
GlobalVars gv = (GlobalVars) getApplicationContext();
Cursor cc = gv.db.getAirportCodes();
while(cc.moveToNext())
{
for (int i = 0; i < cc.getColumnCount(); i++) {
gv.Airport_Codes.add(cc.getString(i));
}
}
final EditText txtUserID = (EditText) findViewById(R.id.txtUserID);
final EditText txtPassword = (EditText) findViewById(R.id.txtPassword);
Button btnLogin = (Button) findViewById(R.id.btnLogin);
btnLogin.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
String userID = txtUserID.getText().toString();
String password = txtPassword.getText().toString();
if (checkLogin(userID, password)) {
Toast.makeText(getApplicationContext(), "Logging in...",
Toast.LENGTH_SHORT).show();
Intent intent = new Intent(v.getContext(),
FASelection.class);
startActivity(intent);
} else {
AlertDialog.Builder ad = new AlertDialog.Builder(Login.this);
ad.setMessage("Login Not Successful");
ad.setNeutralButton("OK",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(),
"Re-Enter Your Info...",
Toast.LENGTH_SHORT).show();
}
});
ad.show();
}
}
});
}
public boolean checkLogin(String u, String p) {
GlobalVars gv = (GlobalVars) getApplicationContext();
Cursor c = gv.db.getUser(u);
User temp = new User();
temp.setUserID(c.getString(c.getColumnIndex("Employee_ID")));
temp.setPassword(c.getString(c.getColumnIndex("Password")));
boolean exists = false;
if(c == null)
return false;
if (temp.UserID.equalsIgnoreCase(u)) {
if (temp.Password.equals(p)) {
gv.user = temp;
gv.PK_Login_Log = (int) gv.db.insertLoginLogInfo(u, 1000);
return true;
} else
exists = false;
}
return exists;
}
}
然后这是我的POSContext(数据库上下文类):
package com.maziz.POS;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
public class POSContext extends SQLiteOpenHelper{
//The Android's default system path of your application database.
private static String DB_PATH = "/data/data/com.maziz.POS/databases/";
private static String DB_NAME = "AndroidPOS.sqlite";
private SQLiteDatabase myDataBase;
private final Context myContext;
/**
* Constructor
* Takes and keeps a reference of the passed context in order to access to the application assets and resources.
* @param context
*/
public POSContext(Context context) {
super(context, DB_NAME, null, 1);
this.myContext = context;
}
/**
* Creates a empty database on the system and rewrites it with your own database.
* */
public void createDataBase() throws IOException{
boolean dbExist = checkDataBase();
if(dbExist){
//do nothing - database already exist
}else{
//By calling this method and empty database will be created into the default system path
//of your application so we are gonna be able to overwrite that database with our database.
this.getReadableDatabase();
try {
copyDataBase();
} catch (IOException e) {
throw new Error("Error copying database");
}
}
}
/**
* Check if the database already exist to avoid re-copying the file each time you open the application.
* @return true if it exists, false if it doesn't
*/
private boolean checkDataBase(){
File dbFile = new File(DB_PATH + DB_NAME);
return dbFile.exists();
/ * SQLiteDatabase checkDB = null;
try{
String myPath = DB_PATH + DB_NAME;
checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
}catch(SQLiteException e){
//database does't exist yet.
}
if(checkDB != null){
checkDB.close();
}
return checkDB != null ? true : false;*/
}
/**
* Copies your database from your local assets-folder to the just created empty database in the
* system folder, from where it can be accessed and handled.
* This is done by transfering bytestream.
* */
private void copyDataBase() throws IOException{
//Open your local db as the input stream
InputStream myInput = myContext.getAssets().open(DB_NAME);
// Path to the just created empty db
String outFileName = DB_PATH + DB_NAME;
//Open the empty db as the output stream
OutputStream myOutput = new FileOutputStream(outFileName);
//transfer bytes from the inputfile to the outputfile
byte[] buffer = new byte[2048];
int length;
while ((length = myInput.read(buffer))>0){
myOutput.write(buffer, 0, length);
}
//Close the streams
myOutput.flush();
myOutput.close();
myInput.close();
}
public void openDataBase() throws SQLException{
//Open the database
String myPath = DB_PATH + DB_NAME;
myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);
}
@Override
public synchronized void close() {
if(myDataBase != null)
myDataBase.close();
super.close();
}
@Override
public void onCreate(SQLiteDatabase db) {
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
// Add your public helper methods to access and get content from the database.
// You could return cursors by doing "return myDataBase.query(....)" so it'd be easy
// to you to create adapters for your views.
public Cursor getUser(String uID)
{
Cursor mCursor = myDataBase.query(true, "FA_Login", new String[] {
"PK_FA_Login", "Airline_ID", "Employee_ID", "Password"},
"Employee_ID = '" + uID + "'", null, null, null, null, null);
if (mCursor != null) {
mCursor.moveToFirst();
}
return mCursor;
}
public Cursor getAirportCodes()
{
Cursor mCursor = myDataBase.query("Airport_Codes", new String[] {
"Airport_Code"
}, null, null, null, null, "Airport_Code");
return mCursor;
}
public Cursor getFlightByOriginDestination(String origin, String dest)
{
Cursor mCursor = myDataBase.query("Inventory_Flight_Schedule", new String[] {
"PK_Inventory_Flight_Schedule", "Flight_Number", "AC_Type", "Time", "Origin", "Destination"
}, "Origin = '" + origin + "' AND Destination = '" + dest + "'", null, null, null, null);
return mCursor;
}
public Cursor getFlightByFlightNumber(String fn)
{
if(fn.equals(""))
fn = "0";
Cursor mCursor = myDataBase.query("Inventory_Flight_Schedule", new String[] {
"PK_Inventory_Flight_Schedule", "Flight_Number", "AC_Type", "Time", "Origin", "Destination"
}, "Flight_Number = " + fn, null, null, null, null);
return mCursor;
}
public Cursor getProductsOnFlight(int pk)
{
Cursor mCursor = myDataBase.query("Inventory_Scheduled", new String[] {
"PK_Product_ID", "Quantity"
}, "PK_Inventory_Flight_Schedule = " + pk, null, null, null, null);
return mCursor;
}
public String getProductCategory(int pk)
{
String c = "";
Cursor mCursor = myDataBase.query("Product_Category_Assigned", new String[] {
"PK_Product_ID", "PK_Category_ID"
}, "PK_Product_ID = " + pk, null, null, null, null);
while (mCursor.moveToNext())
{
c = c + " " + mCursor.getString(mCursor.getColumnIndex("Category_Name"));
}
return c;
}
public Cursor getProductDetailsByProductID(int pID)
{
Cursor mCursor = myDataBase.query("Products", new String[] {
"Product_Description", "Product_Name", "Price", "ImageUri"
}, "PK_Product_ID = " + pID, null, null, null, null);
return mCursor;
}
public ArrayList<Product> getProductSalesDetail(int pkss)
{
ArrayList<Product> productSales = new ArrayList<Product>();
Product temp;
Cursor p = myDataBase.query("Sales_Details", new String[] {
"PK_Product_ID", "Quantity"
}, "PK_Sales_Summary = " + pkss, null, null, null, null);
while(p.moveToNext())
{
int pkproduct = Integer.parseInt(p.getString(p.getColumnIndex("PK_Product_ID")));
Cursor product = getProductDetailsByProductID(pkproduct);
product.moveToFirst();
temp = new Product();
temp.PK_Product_ID = pkproduct;
temp.QuantityInCart = Integer.parseInt(p.getString(p.getColumnIndex("Quantity")));
temp.Product_Name = product.getString(product.getColumnIndex("Product_Name"));
temp.Price = product.getDouble(product.getColumnIndex("Price"));
temp.ImageUri = product.getString(product.getColumnIndex("ImageUri"));
productSales.add(temp);
}
return productSales;
}
public ArrayList<Product> getProductSales(ArrayList<Integer> pkss)
{
ArrayList<Product> productSales = new ArrayList<Product>();
for(int pk: pkss)
{
Cursor p = myDataBase.query("Sales_Details", new String[] {
"PK_Product_ID", "Quantity"
}, "PK_Sales_Summary = " + pk, null, null, null, null);
while(p.moveToNext())
{
int pkproduct = Integer.parseInt(p.getString(p.getColumnIndex("PK_Product_ID")));
Cursor product = getProductDetailsByProductID(pkproduct);
product.moveToFirst();
Product temp;
if(productSales.isEmpty())
{
temp = new Product();
temp.PK_Product_ID = pkproduct;
temp.Quantity = Integer.parseInt(p.getString(p.getColumnIndex("Quantity")));
temp.Product_Name = product.getString(product.getColumnIndex("Product_Name"));
temp.Price = product.getDouble(product.getColumnIndex("Price"));
temp.ImageUri = product.getString(product.getColumnIndex("ImageUri"));
productSales.add(temp);
}
else //if product list is not empty
{
temp = new Product();
boolean inList = false;
for(Product pp: productSales)
{
if(pp.PK_Product_ID == pkproduct)
{
inList = true;
temp.Quantity = temp.Quantity + Integer.parseInt(p.getString(p.getColumnIndex("Quantity")));
break;
}
}
if(!inList)
{
temp.PK_Product_ID = pkproduct;
temp.Quantity = Integer.parseInt(p.getString(p.getColumnIndex("Quantity")));
temp.Product_Name = product.getString(product.getColumnIndex("Product_Name"));
temp.Price = product.getDouble(product.getColumnIndex("Price"));
temp.ImageUri = product.getString(product.getColumnIndex("ImageUri"));
productSales.add(temp);
}
else
{
for(int i = 0; i < productSales.size(); i++)
{
Product pp = productSales.get(i);
if(pp.PK_Product_ID == pkproduct)
{
productSales.get(i).Quantity = productSales.get(i).Quantity + Integer.parseInt(p.getString(p.getColumnIndex("Quantity")));
}
}
}
}
}
}
return productSales;
}
public ArrayList<SalesTransaction> getSalesData(int FlightNumber, String currentDate)
{
Cursor salesData;
ArrayList<Integer> pkflights = new ArrayList<Integer>();
ArrayList<SalesTransaction> st = new ArrayList<SalesTransaction>();
currentDate = currentDate.trim();
String select = "Select PK_Flight_Selected From Flight_Selected Where Flight_Number = '" + FlightNumber + "'";
Cursor mCursor = myDataBase.rawQuery(select, null);
/*myDataBase.query("Flight_Selected", new String[] {
"PK_Flight_Selected"
}, "Flight_Number = " + FlightNumber + " AND Flight_Date = '" + currentDate + "'", null, null, null, null);
*/
while (mCursor.moveToNext())
{
pkflights.add(Integer.parseInt(mCursor.getString(mCursor.getColumnIndex("PK_Flight_Selected"))));
}
for(int i: pkflights)
{
salesData = myDataBase.query("Sales_Summary", new String[] {
"PK_Sales_Summary", "PK_Flight_Selected", "Employee_ID", "Total_Items", "Total_Amount"
}, "PK_Flight_Selected = " + i , null, null, null, null);
while(salesData.moveToNext())
{
SalesTransaction temp = new SalesTransaction();
temp.PK_Sales_Summary = Integer.parseInt(salesData.getString(salesData.getColumnIndex("PK_Sales_Summary")));
temp.PK_Flight_Selected = Integer.parseInt(salesData.getString(salesData.getColumnIndex("PK_Flight_Selected")));
temp.EmployeeID = salesData.getString(salesData.getColumnIndex("Employee_ID"));
temp.items = Integer.parseInt(salesData.getString(salesData.getColumnIndex("Total_Items")));
temp.amount = Double.parseDouble(salesData.getString(salesData.getColumnIndex("Total_Amount")));
Cursor salest = myDataBase.query("Sales_Transactions", new String[] {
"PK_Sales_Transaction", "CC_Name"
}, "PK_Sales_Summary = " + temp.PK_Sales_Summary, null, null, null, null);
while(salest.moveToNext())
{
temp.PK_Sales_Transaction = Integer.parseInt(salest.getString(salest.getColumnIndex("PK_Sales_Transaction")));
temp.CC_Name = salest.getString(salest.getColumnIndex("CC_Name"));
}
st.add(temp);
}
}
return st;
}
public long insertFlightSelectedRecord(int airline_ID, int flight_Number, String o, String d, String fd, String ac)
{
ContentValues cv = new ContentValues();
cv.put("Airline_ID", airline_ID);
cv.put("Flight_Number", flight_Number);
cv.put("Origin", o);
cv.put("Dest", d);
cv.put("Flight_Date", fd.toString());
cv.put("AC_Type", ac);
return myDataBase.insert("Flight_Selected", null, cv);
}
public long insertLoginLogInfo(String e, int device)
{
Date date = new Date();
ContentValues cv = new ContentValues();
cv.put("Employee_ID", e);
cv.put("Login_TimeStamp", date.toString());
cv.put("Device_ID", device);
return myDataBase.insert("FA_Login_Log", null, cv);
}
public long insertSalesSummary(int pk_flight, String EmployeeID, double total_items, double Amount)
{
ContentValues cv = new ContentValues();
cv.put("PK_Flight_Selected", pk_flight);
cv.put("Employee_ID", EmployeeID);
cv.put("Total_Items", total_items);
cv.put("Total_Amount", Amount);
return myDataBase.insert("Sales_Summary", null, cv);
}
public long insertSalesDetails(int pk_salessummary, int pID, int q)
{
ContentValues cv = new ContentValues();
cv.put("PK_Sales_Summary", pk_salessummary);
cv.put("PK_Product_ID", pID);
cv.put("Quantity", q);
return myDataBase.insert("Sales_Details", null, cv);
}
public long insertSalesTransaction(int pkss, double amount, String cctype, String ccnumber, int cccode, String ccName)
{
ContentValues cv = new ContentValues();
cv.put("PK_Sales_Summary", pkss);
cv.put("Amount", amount);
cv.put("CC_Type", cctype);
cv.put("CC_Number", ccnumber);
cv.put("CC_Code", cccode);
cv.put("CC_Name", ccName);
return myDataBase.insert("Sales_Transactions", null, cv);
}
public boolean updateLoginLog(int pk, int pkflight)
{
ContentValues cv = new ContentValues();
cv.put("PK_Flight_Selected", pkflight);
return myDataBase.update("FA_Login_Log", cv, "PK_FA_Login_Log = " + pk, null) > 0;
}
}
错误似乎发生在POSContext中的getAirportCode方法中。
任何帮助都会非常感激。 谢谢!
编辑:
在进一步调试后我安装了Catlog,这是实时错误:
03-23 12:34:12.468 I/ActivityManager(1296): Start proc com.maziz.POS for activity com.maziz.POS/.Login: pid=6250 uid=10051 gids={3003}
03-23 12:34:12.546 I/Database(6250): sqlite returned: error code = 0, msg = Recovered 3 frames from WAL file /data/data/com.maziz.POS/databases/AndroidPOS.sqlite-wal
03-23 12:34:12.546 E/Database(6250): sqlite_prepare_v2(handle, "pragma journal_mode=WAL;") failed for "/data/data/com.maziz.POS/databases/AndroidPOS.sqlite"
03-23 12:34:12.554 E/Database(6250): at com.maziz.POS.POSContext.openDataBase(POSContext.java:135)
03-23 12:34:12.554 E/Database(6250): at com.maziz.POS.GlobalVars.onCreate(GlobalVars.java:32)
03-23 12:34:12.562 W/System.err(6250): at com.maziz.POS.POSContext.openDataBase(POSContext.java:135)
03-23 12:34:12.562 W/System.err(6250): at com.maziz.POS.GlobalVars.onCreate(GlobalVars.java:32)
03-23 12:34:12.625 D/BugSenseHandler(6250): Looking for exceptions in: /data/data/com.maziz.POS/files
03-23 12:34:12.656 D/BugSenseHandler(6250): Transmitting stack trace: java.lang.RuntimeException: Unable to start activity ComponentInfo{com.maziz.POS/com.maziz.POS.Login}: java.lang.NullPointerException
03-23 12:34:12.656 D/BugSenseHandler(6250): at com.maziz.POS.POSContext.getAirportCodes(POSContext.java:178)
03-23 12:34:12.656 D/BugSenseHandler(6250): at com.maziz.POS.Login.onCreate(Login.java:29)
03-23 12:34:14.648 D/BugSenseHandler(6250): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.maziz.POS/com.maziz.POS.Login}: java.lang.NullPointerException
03-23 12:34:14.648 D/BugSenseHandler(6250): at com.maziz.POS.POSContext.getAirportCodes(POSContext.java:178)
03-23 12:34:14.648 D/BugSenseHandler(6250): at com.maziz.POS.Login.onCreate(Login.java:29)
03-23 12:34:14.648 E/AndroidRuntime(6250): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.maziz.POS/com.maziz.POS.Login}: java.lang.NullPointerException
03-23 12:34:14.648 E/AndroidRuntime(6250): at com.maziz.POS.POSContext.getAirportCodes(POSContext.java:178)
03-23 12:34:14.648 E/AndroidRuntime(6250): at com.maziz.POS.Login.onCreate(Login.java:29)
03-23 12:34:15.492 W/ActivityManager(1296): Force finishing activity com.maziz.POS/.Login
03-23 12:34:16.000 W/ActivityManager(1296): Activity pause timeout for HistoryRecord{407109b8 com.maziz.POS/.Login}
03-23 12:34:17.320 I/ActivityManager(1296): Process com.maziz.POS (pid 6250) has died.
03-23 12:34:17.718 E/AnrParser(1432): Deleted file/data/anr/anrlogs/ANR_com.maziz.POS_20120323-123414.log
03-23 12:34:17.718 E/AnrParser(1432): Deleted file/data/anr/anrlogs/com.maziz.POS-logcat.log
03-23 12:34:26.148 W/ActivityManager(1296): Activity destroy timeout for HistoryRecord{407109b8 com.maziz.POS/.Login}
答案 0 :(得分:0)
可以在getAirportCodes中生成NullPointerException的唯一对象是myDataBase。如果文件确实存在,您应该检查openDataBase。我还注意到你有一个数据库路径的常量。也许这在您的设备上是不正确的。
要检查应用程序的数据库路径,请使用getDatabasePath,请参阅下面的链接。