Android-приложение работает на эмуляторе, но вылетает при запуске на устройстве

1

Я прочитал тысячи страниц и еще не нашел решения. Я относительно новичок в Android Development, и это первый раз, когда я развертываю любое приложение на мобильном устройстве, и моя проблема заключается в том, что приложение работает на моем эмуляторе безупречно, но на моем устройстве он падает при запуске. Я как бы указал на ошибку, связанную с доступом к данным из базы данных, которую я упаковываю с помощью приложения.

В основном, мое первое действие вызывает функцию для извлечения кода аэропорта из БД. Он получает функцию в моем файле 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 (DB Context Class):

    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 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;
}

    }

Ошибка, похоже, происходит в методе getAirportCode в POSContext.

Любая помощь была бы высоко оценена. Благодарю!

РЕДАКТИРОВАТЬ:

после дальнейшей отладки я установил 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
    Вы пытались отлаживать? NullPointerException обычно означает, что вы вызываете методы для переменной объекта, которая не была правильно инициализирована (то есть содержит значение null). Вы можете отлаживать на своем устройстве, просто подключите его с помощью кабеля USB.
  • 0
    Да, я делаю это, но для меня не имеет смысла, что он работает на моем эмуляторе, но не на моем устройстве. Я только что отредактировал свое сообщение с новой копией logcat, и теперь я вижу, что не удается открыть БД, но все равно не повезло. Спасибо за ваш быстрый ответ!
Показать ещё 3 комментария
Теги:

1 ответ

0

Единственным объектом, который может генерировать исключение NullPointerException в getAirportCodes, является myDataBase. Вы должны проверить в openDataBase, если файл действительно существует. Я также заметил, что у вас есть константа для пути к базе данных. Возможно, это неверно на вашем устройстве.

Чтобы проверить путь к базе данных вашего приложения, используйте getDatabasePath, см. Ссылку ниже.

http://developer.android.com/reference/android/content/ContextWrapper.html#getDatabasePath(java.lang.String)

  • 0
    Я изменил его, чтобы использовать getDatabasePath, но все еще не пошел. Это так странно. Он отлично работает на эмуляторе, но на устройстве дает мне эти ошибки. Я также стер эмулятор без каких-либо разработанных мною приложений и их данных.
  • 0
    Может ли быть так, что моя БД составляет 1,21 МБ, а папка «Ресурсы» - около 30 МБ?
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню