Android 应用程序强制关闭设备

发布于 2024-11-07 09:49:18 字数 6525 浏览 1 评论 0原文

在模拟器上,应用程序运行良好。在设备上,当我尝试将数据库复制到应用程序的数据库并执行查询时,应用程序会强制关闭。知道为什么会发生这种情况吗?我是否必须请求任何类型的权限或清单中的某些内容才能运行?

Database.Java

public class Database extends SQLiteOpenHelper{

//The Android's default system path of your application database.
private static String DB_PATH = "/data/data/gr.BHC.www/databases/";

//Name of the Database to be created.
private static String DB_NAME = "BHCLibrary3.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 Database(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{

    //First we check if the database already exists, Method declared later
    boolean dbExist = checkDataBase(); 

    if(dbExist){
        //do nothing - database already exists
    }else{

        //By calling this method an empty database will be created into the default system path
           //of your application so we are going to be able to overwrite that database with our database.
        this.getReadableDatabase();

        try {
            copyDataBase(); //Method declared later

        } 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() {
    //SQLiteDatabase checkdb = null;
    boolean checkdb = false;
    try{
        String myPath = DB_PATH + DB_NAME;
        File dbfile = new File(myPath);
        //checkdb = SQLiteDatabase.openDatabase(myPath,null,SQLiteDatabase.OPEN_READWRITE);
        checkdb = dbfile.exists();
    }
    catch(SQLiteException e){
        System.out.println("Database doesn't exist");
    }

    return checkdb;
}



/**
 * 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 transferring byte stream.
 * */


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[1024];
    int length;
    while ((length = myInput.read(buffer))>0){
        myOutput.write(buffer, 0, length);
    }

    //Close the streams
    myOutput.flush();
    myOutput.close();
    myInput.close();

}


//Opening the Database
public void openDataBase() throws SQLException{

    //Open the database
    String myPath = DB_PATH + DB_NAME;
    myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);


}

//Finally overriding a few methods as required

@Override
public synchronized void close() {

        if(myDataBase != null)
            myDataBase.close();

        super.close();

}

@Override
public void onCreate(SQLiteDatabase db) {

    //First we check if the database already exists, Method declared later
    boolean dbExist = checkDataBase(); 

    if(dbExist){
        //do nothing - database already exists
    }else{

        //By calling this method an empty database will be created into the default system path
           //of your application so we are going to be able to overwrite that database with our database.
        this.getReadableDatabase();

        try {
            copyDataBase(); //Method declared later

        } catch (IOException e) {
            throw new Error("Error copying database");
          }
    }
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

}

}

Results.java (我运行查询的活动)

public class SearchResults extends ListActivity {

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.searchresults);


    Database myDbHelper = new Database(null);
    myDbHelper = new Database(this);

  }



 // Get the intent, verify the action and get the query
    Intent intent = getIntent();
    String query = intent.getStringExtra(SearchManager.QUERY);


    SQLiteDatabase myDb = myDbHelper.getReadableDatabase();

 //Executing our query against the server using rawQuery and getting the cursor
    String select="SELECT DISTINCT b._ISBN as _id, b.BookTitle, b.Edition, b.Year, b.Pages, b.Rating, c.Category, p.Publisher, w.LastName" +
            "   FROM" +
            "   Books b" +
            "   JOIN Categories_Books cb ON cb._Books_ISBN = _id" +
            "   JOIN Categories c ON c._CategoryID = cb._Categories_CategoryID" +
            "   JOIN Publishers p ON p._PublisherID = b.PublisherID" +
            "   JOIN Writers_Books wb ON wb._Books_ISBN = _id" +
            "   JOIN Writers w ON w._WriterID = wb._Writers_WriterID" +
            "   WHERE b.BookTitle LIKE '%" + query +"%'" +
            "   OR c.Category LIKE '%" + query +"%'" +
            "   OR p.Publisher LIKE '%" + query +"%'" +
            "   OR w.LastName LIKE '%" + query +"%'" +
            "   OR _id LIKE '%" + query +"%'" +
            "   GROUP BY b.BookTitle";


    Cursor c = myDb.rawQuery(select, null);
    startManagingCursor(c);



 // the desired columns to be bound
    String[] columns = new String[] { "Books.BookTitle", "Publishers.Publisher" }; 
 // the XML defined views which the data will be bound to
    int[] to = new int[] { R.id.ISBN_entry, R.id.Title_entry };

 //Getting results into our listview
    try
    {
        SimpleCursorAdapter mAdapter = new SimpleCursorAdapter(this, R.layout.listlayout, c, columns, to);
        this.setListAdapter(mAdapter);
    }
    catch( Exception e)
    {

    }
}

}

如有帮助,我们将不胜感激。

编辑:我得到的错误是:java.lang.runtimeexception:无法启动活动Componentinfo(gr.BHC.www/gr.BHC.www.SearchResults},然后各种异常说表格书籍等不存在。

编辑2:我看到了例外的是,我通常与内容提供商相关,但我仍然不明白为什么我会得到它。

On the Emulator the app runs fine. On the device the moment im trying to copy my database over the application's database and execute a query the app force closes. Any idea why this could be happening? Do i have to request any kind of permissions or something in manifest for it to run?

Database.Java

public class Database extends SQLiteOpenHelper{

//The Android's default system path of your application database.
private static String DB_PATH = "/data/data/gr.BHC.www/databases/";

//Name of the Database to be created.
private static String DB_NAME = "BHCLibrary3.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 Database(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{

    //First we check if the database already exists, Method declared later
    boolean dbExist = checkDataBase(); 

    if(dbExist){
        //do nothing - database already exists
    }else{

        //By calling this method an empty database will be created into the default system path
           //of your application so we are going to be able to overwrite that database with our database.
        this.getReadableDatabase();

        try {
            copyDataBase(); //Method declared later

        } 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() {
    //SQLiteDatabase checkdb = null;
    boolean checkdb = false;
    try{
        String myPath = DB_PATH + DB_NAME;
        File dbfile = new File(myPath);
        //checkdb = SQLiteDatabase.openDatabase(myPath,null,SQLiteDatabase.OPEN_READWRITE);
        checkdb = dbfile.exists();
    }
    catch(SQLiteException e){
        System.out.println("Database doesn't exist");
    }

    return checkdb;
}



/**
 * 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 transferring byte stream.
 * */


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[1024];
    int length;
    while ((length = myInput.read(buffer))>0){
        myOutput.write(buffer, 0, length);
    }

    //Close the streams
    myOutput.flush();
    myOutput.close();
    myInput.close();

}


//Opening the Database
public void openDataBase() throws SQLException{

    //Open the database
    String myPath = DB_PATH + DB_NAME;
    myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);


}

//Finally overriding a few methods as required

@Override
public synchronized void close() {

        if(myDataBase != null)
            myDataBase.close();

        super.close();

}

@Override
public void onCreate(SQLiteDatabase db) {

    //First we check if the database already exists, Method declared later
    boolean dbExist = checkDataBase(); 

    if(dbExist){
        //do nothing - database already exists
    }else{

        //By calling this method an empty database will be created into the default system path
           //of your application so we are going to be able to overwrite that database with our database.
        this.getReadableDatabase();

        try {
            copyDataBase(); //Method declared later

        } catch (IOException e) {
            throw new Error("Error copying database");
          }
    }
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

}

}

And Results.java (The activity i run my query)

public class SearchResults extends ListActivity {

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.searchresults);


    Database myDbHelper = new Database(null);
    myDbHelper = new Database(this);

  }



 // Get the intent, verify the action and get the query
    Intent intent = getIntent();
    String query = intent.getStringExtra(SearchManager.QUERY);


    SQLiteDatabase myDb = myDbHelper.getReadableDatabase();

 //Executing our query against the server using rawQuery and getting the cursor
    String select="SELECT DISTINCT b._ISBN as _id, b.BookTitle, b.Edition, b.Year, b.Pages, b.Rating, c.Category, p.Publisher, w.LastName" +
            "   FROM" +
            "   Books b" +
            "   JOIN Categories_Books cb ON cb._Books_ISBN = _id" +
            "   JOIN Categories c ON c._CategoryID = cb._Categories_CategoryID" +
            "   JOIN Publishers p ON p._PublisherID = b.PublisherID" +
            "   JOIN Writers_Books wb ON wb._Books_ISBN = _id" +
            "   JOIN Writers w ON w._WriterID = wb._Writers_WriterID" +
            "   WHERE b.BookTitle LIKE '%" + query +"%'" +
            "   OR c.Category LIKE '%" + query +"%'" +
            "   OR p.Publisher LIKE '%" + query +"%'" +
            "   OR w.LastName LIKE '%" + query +"%'" +
            "   OR _id LIKE '%" + query +"%'" +
            "   GROUP BY b.BookTitle";


    Cursor c = myDb.rawQuery(select, null);
    startManagingCursor(c);



 // the desired columns to be bound
    String[] columns = new String[] { "Books.BookTitle", "Publishers.Publisher" }; 
 // the XML defined views which the data will be bound to
    int[] to = new int[] { R.id.ISBN_entry, R.id.Title_entry };

 //Getting results into our listview
    try
    {
        SimpleCursorAdapter mAdapter = new SimpleCursorAdapter(this, R.layout.listlayout, c, columns, to);
        this.setListAdapter(mAdapter);
    }
    catch( Exception e)
    {

    }
}

}

Help would be appreciated.

EDIT: The error im getting is : java.lang.runtimeexception: Unable to start activity Componentinfo(gr.BHC.www/gr.BHC.www.SearchResults} and then various exceptions saying table books etc dont exist.

EDIT2: I saw the exception im getting usually related with content providers but i still cant figure out why i'd get that.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

暖风昔人 2024-11-14 09:49:18

我想我解决了问题。我对你的代码做了一些更改,现在它可以工作了。以下是代码:

SearchResults.java

public class SearchResults extends ListActivity {

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
//      setContentView(R.layout.searchresults);

        DbManager myDbHelper = new DbManager(null);
        myDbHelper = new DbManager(this);

        // Get the intent, verify the action and get the query
        
        myDbHelper.createNewDatabase();

        
        try {
            myDbHelper.open();
            Log.d("Search Results", "database opened");
        } catch (SQLException sqle) {
            throw sqle;
        }

        Intent intent = getIntent();
        String query = intent.getStringExtra(SearchManager.QUERY);

        // Executing our query against the server using rawQuery and getting the
        // cursor
        String select = "SELECT DISTINCT b._ISBN as _id, b.BookTitle, b.Edition, b.Year, b.Pages, b.Rating, c.Category, p.Publisher, w.LastName"
                + "   FROM"
                + "   Books b"
                + "   JOIN Categories_Books cb ON cb._Books_ISBN = _id"
                + "   JOIN Categories c ON c._CategoryID = cb._Categories_CategoryID"
                + "   JOIN Publishers p ON p._PublisherID = b.PublisherID"
                + "   JOIN Writers_Books wb ON wb._Books_ISBN = _id"
                + "   JOIN Writers w ON w._WriterID = wb._Writers_WriterID"
                + "   WHERE b.BookTitle LIKE '%"
                + query
                + "%'"
                + "   OR c.Category LIKE '%"
                + query
                + "%'"
                + "   OR p.Publisher LIKE '%"
                + query
                + "%'"
                + "   OR w.LastName LIKE '%"
                + query
                + "%'"
                + "   OR _id LIKE '%"
                + query
                + "%'"
                + "   GROUP BY b.BookTitle";

        Cursor c = myDbHelper.rawQ(select);
        startManagingCursor(c);

        // the desired columns to be bound
        String[] columns = new String[] { "Books.BookTitle",
                "Publishers.Publisher" };
        // the XML defined views which the data will be bound to
        int[] to = new int[] { R.id.ISBN_entry, R.id.Title_entry };

        // Getting results into our listview
        try {
            SimpleCursorAdapter mAdapter = new SimpleCursorAdapter(this,
                    R.layout.listlayout, c, columns, to);
            this.setListAdapter(mAdapter);
        } catch (Exception e) {

        }
    }
}

以及新的数据库助手 DbManager:

DbManager.java

public class DbManager extends SQLiteOpenHelper {

    private static final String DB_NAME = "BHCLibrary3.sqlite";
    private static final String DB_PATH = "/data/data/gr.BHC.www/databases/";
    private static final Integer DB_VERSION = 1;
    private static final String TAG = "DbManager";
    private final Context context;
    private SQLiteDatabase db;
    private DbManager dbManager;

    public DbManager(Context context) {
        super(context, DB_NAME, null, DB_VERSION);
        this.context = context;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("CREATE TABLE 'notes' (_id integer primary key autoincrement, title text not null);");
    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
    }

    public DbManager open() {
        dbManager = new DbManager(context);
        db = dbManager.getWritableDatabase();
        return this;
    }

    public void createNewDatabase() {
        InputStream assetsDB = null;
        try {
            assetsDB = context.getAssets().open(DB_NAME);
            OutputStream dbOut = new FileOutputStream(DB_PATH + DB_NAME);

            byte[] buffer = new byte[1024];
            int length;
            while ((length = assetsDB.read(buffer)) > 0) {
                dbOut.write(buffer, 0, length);
            }

            dbOut.flush();
            dbOut.close();
            assetsDB.close();
            Log.i(TAG, "New database created...");
        } catch (IOException e) {
            Log.e(TAG, "Could not create new database...");
            e.printStackTrace();
        }
    }

    public Cursor rawQ(String select) {
        return db.rawQuery(select, null);
    }
}

I think I solved the problem. I made some changes on your codes and now it is working. Here are the codes:

SearchResults.java

public class SearchResults extends ListActivity {

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
//      setContentView(R.layout.searchresults);

        DbManager myDbHelper = new DbManager(null);
        myDbHelper = new DbManager(this);

        // Get the intent, verify the action and get the query
        
        myDbHelper.createNewDatabase();

        
        try {
            myDbHelper.open();
            Log.d("Search Results", "database opened");
        } catch (SQLException sqle) {
            throw sqle;
        }

        Intent intent = getIntent();
        String query = intent.getStringExtra(SearchManager.QUERY);

        // Executing our query against the server using rawQuery and getting the
        // cursor
        String select = "SELECT DISTINCT b._ISBN as _id, b.BookTitle, b.Edition, b.Year, b.Pages, b.Rating, c.Category, p.Publisher, w.LastName"
                + "   FROM"
                + "   Books b"
                + "   JOIN Categories_Books cb ON cb._Books_ISBN = _id"
                + "   JOIN Categories c ON c._CategoryID = cb._Categories_CategoryID"
                + "   JOIN Publishers p ON p._PublisherID = b.PublisherID"
                + "   JOIN Writers_Books wb ON wb._Books_ISBN = _id"
                + "   JOIN Writers w ON w._WriterID = wb._Writers_WriterID"
                + "   WHERE b.BookTitle LIKE '%"
                + query
                + "%'"
                + "   OR c.Category LIKE '%"
                + query
                + "%'"
                + "   OR p.Publisher LIKE '%"
                + query
                + "%'"
                + "   OR w.LastName LIKE '%"
                + query
                + "%'"
                + "   OR _id LIKE '%"
                + query
                + "%'"
                + "   GROUP BY b.BookTitle";

        Cursor c = myDbHelper.rawQ(select);
        startManagingCursor(c);

        // the desired columns to be bound
        String[] columns = new String[] { "Books.BookTitle",
                "Publishers.Publisher" };
        // the XML defined views which the data will be bound to
        int[] to = new int[] { R.id.ISBN_entry, R.id.Title_entry };

        // Getting results into our listview
        try {
            SimpleCursorAdapter mAdapter = new SimpleCursorAdapter(this,
                    R.layout.listlayout, c, columns, to);
            this.setListAdapter(mAdapter);
        } catch (Exception e) {

        }
    }
}

And your new database helper, DbManager:

DbManager.java

public class DbManager extends SQLiteOpenHelper {

    private static final String DB_NAME = "BHCLibrary3.sqlite";
    private static final String DB_PATH = "/data/data/gr.BHC.www/databases/";
    private static final Integer DB_VERSION = 1;
    private static final String TAG = "DbManager";
    private final Context context;
    private SQLiteDatabase db;
    private DbManager dbManager;

    public DbManager(Context context) {
        super(context, DB_NAME, null, DB_VERSION);
        this.context = context;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("CREATE TABLE 'notes' (_id integer primary key autoincrement, title text not null);");
    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
    }

    public DbManager open() {
        dbManager = new DbManager(context);
        db = dbManager.getWritableDatabase();
        return this;
    }

    public void createNewDatabase() {
        InputStream assetsDB = null;
        try {
            assetsDB = context.getAssets().open(DB_NAME);
            OutputStream dbOut = new FileOutputStream(DB_PATH + DB_NAME);

            byte[] buffer = new byte[1024];
            int length;
            while ((length = assetsDB.read(buffer)) > 0) {
                dbOut.write(buffer, 0, length);
            }

            dbOut.flush();
            dbOut.close();
            assetsDB.close();
            Log.i(TAG, "New database created...");
        } catch (IOException e) {
            Log.e(TAG, "Could not create new database...");
            e.printStackTrace();
        }
    }

    public Cursor rawQ(String select) {
        return db.rawQuery(select, null);
    }
}
破晓 2024-11-14 09:49:18

您的数据库大小似乎超过 1 MB。在这种情况下,您需要将其作为 .jpg 存储在资产文件夹中,然后将其复制。这是因为 Android 对文本资源的大小进行了限制。

Looks like the size of your database exceeds one MB. In that case you need to store it in the assets folder as .jpg and then copy it over. This is because Android places a restriction on the size of the text assets.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文