在我的下一个 Android 应用程序更新中使用新的数据库版本覆盖现有的已发布 Sqlite DB

2024-02-06

我想覆盖旧应用程序版本附带的现有数据库,并在下一个应用程序更新中使用新完全填充的数据库。然而, onUpgrade() 永远不会被调用,尽管我尝试在将 DB_version 传递给 SQLiteOpenHelper 类时更改它。

public class DataBaseHelper extends SQLiteOpenHelper {

    private static Context mContext;
    private static String DB_PATH = "/data/data/<app Package>/databases/";;
    private static final String DBNAME = "DB.db";
    private static DataBaseHelper sInstance;
    private static final int version = 2;


    public static synchronized DataBaseHelper getInstance(Context context) {
        // Use the application context, which will ensure that you
        // don't accidentally leak an Activity's context.
        if (sInstance == null) {
            sInstance = new DataBaseHelper(context.getApplicationContext());
        }
        return sInstance;
    }

    public DataBaseHelper(Context context, String s){
        super(context, DBNAME, null, version);

    }

    private DataBaseHelper(Context context) {
        super(context, DBNAME, null, version);
        mContext = context;

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            DB_PATH = context.getApplicationInfo().dataDir + "/databases/";
        } else {
            DB_PATH = "/data/data/" + context.getPackageName() + "/databases/";
        }

        new Handler().post(new Runnable() {

            @Override
            public void run() {
                // If u want to Copy Database from Assets.
                try {
                    CopyAndCreateDataBase();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
    }


    // If database not exists copy it from the assets
    public void CopyAndCreateDataBase() throws IOException {
        boolean mDataBaseExist = checkDataBase();
        if (!mDataBaseExist) {
            this.getReadableDatabase();
            this.getWritableDatabase();
            this.close();
            try {
                // Copy the database from assests
                copyDataBase();
                String mPath = DB_PATH + DBNAME;
            } catch (IOException mIOException) {
                throw new Error("ErrorCopyingDataBase");
            }
        }
         //FOR DB TESTING PURPOSES
        else{
            Log.d("DB STATUS:", "Database Already Exists!!!!!!!!!");
        }
    }


    // Check that the database exists here: /data/data/yourpackage/databases/DatabaseName
    private boolean checkDataBase() {
        File dbFile = new File(DB_PATH + DBNAME);
        // Log.v("dbFile", dbFile + "   "+ dbFile.exists());
        return dbFile.exists();
    }

    // Copy the database from assets
    private void copyDataBase() throws IOException {
        InputStream mInput = mContext.getAssets().open(DBNAME);
        String outFileName = DB_PATH + DBNAME;
        OutputStream mOutput = new FileOutputStream(outFileName);
        byte[] mBuffer = new byte[1024];
        int mLength;
        while ((mLength = mInput.read(mBuffer)) > 0) {
            mOutput.write(mBuffer, 0, mLength);
        }
        Log.d("DB STATUS:", "Daatabase Created ----------------"); //FOR DB TESTING PURPOSES
        mOutput.flush();
        mOutput.close();
        mInput.close();
    }

    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {

    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
        Log.d("Database Versions:", "old:"+i+"\nnew:"+i1);

    }
}

我尝试了很多方法来触发 onUpgrade() 方法,例如调用 getReadableDatabase() 和 getWritableDatabase(,但不幸的是它确实有效。我想用新发布的数据库覆盖现有的数据库。


我相信你的问题(第一期,请阅读完整答案)可能正在使用处理程序。当然,测试可用代码会导致意外结果(数据库始终报告为存在,因此永远不会从资产中复制数据库,如果数据库存在,则永远不会调用升级时(我的猜测是,由于隐式打开,数据库已经打开,因此没有尝试进行打开处理))。

更改为使用:-

    try {
        CopyAndCreateDataBase();
    } catch (IOException e) {
        e.printStackTrace();
    }

    /*
    new Handler().post(new Runnable() {

        @Override
        public void run() {
            // If u want to Copy Database from Assets.
            try {
                CopyAndCreateDataBase();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    });
    */

产生预期的结果,例如:-

07-04 06:55:38.836 4365-4365/aso.so56873021recopydb D/DBEXISTS: The database /data/user/0/aso.so56873021recopydb/databases/DB.db was found.
07-04 06:55:38.836 4365-4365/aso.so56873021recopydb D/DB STATUS:: Database Already Exists!!!!!!!!!
07-04 06:55:38.838 4365-4365/aso.so56873021recopydb D/Database Versions:: old:1
    new:2
  • 请注意,在测试代码以确定问题时添加了 DBEXISTS 消息。

测试在活动中使用了以下代码:-

public class MainActivity extends AppCompatActivity {


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        DataBaseHelper mDBHlpr = DataBaseHelper.getInstance(this);
        Cursor csr = mDBHlpr.getWritableDatabase().query("sqlite_master",null,null,null,null,null,null);
        DatabaseUtils.dumpCursor(csr);
    }
}

第 2 部分 - 升级

简而言之,即使您可以致电,也存在问题升级时当修复上一个问题后版本增加时升级时被调用时,数据库已经打开,复制新数据库将被有效地撤消,因为旧数据库将覆盖新复制的数据库,从而导致更改丢失。

相反,我建议检查、复制和覆盖数据库prior实例化数据库助手,例如在里面获取实例 method.

因此,我建议使用以下数据库助手(请参阅所做更改的评论):-

public class DataBaseHelper extends SQLiteOpenHelper {

    private static Context mContext;
    //private static String DB_PATH = "/data/data/<app Package>/databases/"; //NOT NEEDED Contexts getDatabasePath used instead
    private static final String DBNAME = "DB.db";
    private static DataBaseHelper sInstance;
    private static final int version = 2;


    public static synchronized DataBaseHelper getInstance(Context context) {
        // Use the application context, which will ensure that you
        // don't accidentally leak an Activity's context.
        checkDB(context.getApplicationContext(),DBNAME,version); //<<<<<<<<<< do the stuff before DatabaseHelper instantiation
        if (sInstance == null) {
            sInstance = new DataBaseHelper(context.getApplicationContext());
        }
        return sInstance;
    }

    private DataBaseHelper(Context context) {
        super(context, DBNAME, null, version);
        mContext = context;
    }

    // Copy the database from assets
    //<<<<<<<<<< CHANGED TO USE getDatabasepath requiring Context to be passed
    private static void copyDataBase(Context context) throws IOException {
        InputStream mInput = context.getAssets().open(DBNAME);
        String outFileName = context.getDatabasePath(DBNAME).toString();
        OutputStream mOutput = new FileOutputStream(outFileName);
        Log.d("DBCOPY","DB Copy inititaed"); //<<<<<<<<<< ADDED FOR TESTING
        byte[] mBuffer = new byte[1024];
        int mLength;
        int bytescopied = 0;
        while ((mLength = mInput.read(mBuffer)) > 0) {
            mOutput.write(mBuffer, 0, mLength);
            bytescopied = bytescopied + mLength;
        }
        Log.d("DBCOPY", "Database copied. " + String.valueOf(bytescopied) + " bytes copied." ); //<<<<<<<<<< ADDED FOR TESTING
        Log.d("DB STATUS:", "Daatabase Created ----------------"); //FOR DB TESTING PURPOSES
        mOutput.flush();
        mOutput.close();
        mInput.close();
    }

    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {

    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
        //<<<<<<<<<< ONLY USE ME FOR SCHEMA CHANGES !!!!NOT!!!! new DB copy
        Log.d("Database Versions:", "old:"+i+"\nnew:"+i1);
    }

    //<<<<<<<<<< NEW 
    private static void checkDB(Context context, String dbname, int version) {
        int dbversion;
        // Note uses the Contexts getDatabasePath
        File dbfile = new File(context.getDatabasePath(dbname).toString());
        if (!dbfile.exists()) {
            //<<<<<<<<<< create the databases directory (or whatever it is the future)
            if (!dbfile.getParentFile().exists()) {
                dbfile.getParentFile().mkdirs();
            }
            //<<<<<<<<<< Now do the copy of the initial DB 
            //<<<<<<<<<< Note new install will copy the latest DB
            try {
                copyDataBase(context);
            } catch (IOException e) {
                e.printStackTrace();
                throw new Error("Error copying initial Database.");
            }
        } 

        // If the database file does exist then retrieve the version
        else {


            SQLiteDatabase db = SQLiteDatabase.openDatabase(context.getDatabasePath(dbname).toString(),null,SQLiteDatabase.OPEN_READWRITE);
            dbversion = db.getVersion();
            Log.d("DBVERSION","The stored database version is " + String.valueOf(dbversion));
            db.close();

            //<<<<<<<<<< if the database's version is less than the coded version then copy the DB
            //<<<<<<<<<< NOTE!!!! always assumes new version = new copy
            //<<<<<<<<<< IF NOt WANTED THEN DO SPECIFIC VERSION CHECKING 
            if (dbversion <  version) {

                //<<<<<<<<<<<< EXAMPLE skip copy on version 10 >>>>>>>>>>
                //<TODO> Remove example check if not needed
                if (dbversion < version && version == 10) {
                    return;
                }
                //<<<<<<<<<< For Android 9+ delete the -wal and -shm files if copying database
                if (new File(context.getDatabasePath(dbname).toString() + "-wal").exists()) {
                    new File(context.getDatabasePath(dbname).toString() + "-wal").delete();
                }
                if (new File(context.getDatabasePath(dbname).toString() + "-shm").exists()) {
                    new File(context.getDatabasePath(dbname).toString() + "-shm").delete();
                }
                try {
                    copyDataBase(context);
                } catch (IOException e) {
                    e.printStackTrace();
                    throw new Error("Error copying upgraded database");
                }
            }
        }
    }
}

Testing

以上已经测试过。测试基于两个数据库(完全不同),在活动中使用以下内容:-

public class MainActivity extends AppCompatActivity {


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        DataBaseHelper mDBHlpr = DataBaseHelper.getInstance(this);
        Cursor csr = mDBHlpr.getWritableDatabase().query("sqlite_master",null,null,null,null,null,null);
        DatabaseUtils.dumpCursor(csr);
    }
}

以下是资产文件夹:-

  • 原始数据库被OLDDB.db复制到DB.db。 NEWDB.db 将是后续的新数据库。

测试在 API 23 和 API 28(Oreo so Pie+ 和 WAL)两种设备上进行。

Stage 1

首先,应用程序使用上述文件运行,版本设置为1。导致日志包含:-

07-04 10:20:32.120 8154-8154/aso.so56873021recopydb D/DBCOPY: DB Copy inititaed
07-04 10:20:32.120 8154-8154/aso.so56873021recopydb D/DBCOPY: Database copied. 36864 bytes copied.
07-04 10:20:32.120 8154-8154/aso.so56873021recopydb D/DB STATUS:: Daatabase Created ----------------
07-04 10:20:32.140 8154-8154/aso.so56873021recopydb I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@6e2c433
07-04 10:20:32.140 8154-8154/aso.so56873021recopydb I/System.out: 0 {
07-04 10:20:32.140 8154-8154/aso.so56873021recopydb I/System.out:    type=table
07-04 10:20:32.140 8154-8154/aso.so56873021recopydb I/System.out:    name=android_metadata
07-04 10:20:32.140 8154-8154/aso.so56873021recopydb I/System.out:    tbl_name=android_metadata
07-04 10:20:32.140 8154-8154/aso.so56873021recopydb I/System.out:    rootpage=3
07-04 10:20:32.140 8154-8154/aso.so56873021recopydb I/System.out:    sql=CREATE TABLE android_metadata (locale TEXT)
07-04 10:20:32.140 8154-8154/aso.so56873021recopydb I/System.out: }
07-04 10:20:32.140 8154-8154/aso.so56873021recopydb I/System.out: 1 {
07-04 10:20:32.140 8154-8154/aso.so56873021recopydb I/System.out:    type=table
07-04 10:20:32.140 8154-8154/aso.so56873021recopydb I/System.out:    name=room_master_table
07-04 10:20:32.140 8154-8154/aso.so56873021recopydb I/System.out:    tbl_name=room_master_table
07-04 10:20:32.140 8154-8154/aso.so56873021recopydb I/System.out:    rootpage=4
07-04 10:20:32.140 8154-8154/aso.so56873021recopydb I/System.out:    sql=CREATE TABLE room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)
07-04 10:20:32.140 8154-8154/aso.so56873021recopydb I/System.out: }
..........
  • 36K 复制
  • 备注表房间主桌

API 28 设备上的类似结果:-

2019-07-04 10:22:33.082 4532-4532/aso.so56873021recopydb D/DBCOPY: DB Copy inititaed
2019-07-04 10:22:33.083 4532-4532/aso.so56873021recopydb D/DBCOPY: Database copied. 36864 bytes copied.
2019-07-04 10:22:33.083 4532-4532/aso.so56873021recopydb D/DB STATUS:: Daatabase Created ----------------
2019-07-04 10:22:33.088 4532-4532/aso.so56873021recopydb I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@2f7f7bc
2019-07-04 10:22:33.089 4532-4532/aso.so56873021recopydb I/System.out: 0 {

Stage 2

应用程序再次运行,结果没有变化(即没有数据库副本):-

07-04 10:24:13.642 8244-8244/? D/DBVERSION: The stored database version is 1
07-04 10:24:13.644 8244-8244/? I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@8c743f0

在 API 28 设备上:-

2019-07-04 10:26:24.531 4620-4620/? D/DBVERSION: The stored database version is 1
2019-07-04 10:26:24.536 4620-4620/? I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@877f345

Stage 3

资产文件夹中的文件更改为:-

应用程序重新运行无需更改版本 :-

无副本和原始数据:-

07-04 10:30:01.838 8369-8369/? D/DBVERSION: The stored database version is 1
07-04 10:30:01.840 8369-8369/? I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@8c743f0
07-04 10:30:01.840 8369-8369/? I/System.out: 0 {
07-04 10:30:01.840 8369-8369/? I/System.out:    type=table
07-04 10:30:01.840 8369-8369/? I/System.out:    name=android_metadata
07-04 10:30:01.840 8369-8369/? I/System.out:    tbl_name=android_metadata
07-04 10:30:01.840 8369-8369/? I/System.out:    rootpage=3
07-04 10:30:01.840 8369-8369/? I/System.out:    sql=CREATE TABLE android_metadata (locale TEXT)
07-04 10:30:01.840 8369-8369/? I/System.out: }
07-04 10:30:01.840 8369-8369/? I/System.out: 1 {
07-04 10:30:01.840 8369-8369/? I/System.out:    type=table
07-04 10:30:01.840 8369-8369/? I/System.out:    name=room_master_table

在 API 28 上:-

2019-07-04 10:31:11.591 4757-4757/aso.so56873021recopydb D/DBVERSION: The stored database version is 1
2019-07-04 10:31:11.596 4757-4757/aso.so56873021recopydb I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@877f345
2019-07-04 10:31:11.596 4757-4757/aso.so56873021recopydb I/System.out: 0 {
2019-07-04 10:31:11.596 4757-4757/aso.so56873021recopydb I/System.out:    type=table
2019-07-04 10:31:11.596 4757-4757/aso.so56873021recopydb I/System.out:    name=android_metadata
2019-07-04 10:31:11.596 4757-4757/aso.so56873021recopydb I/System.out:    tbl_name=android_metadata
2019-07-04 10:31:11.597 4757-4757/aso.so56873021recopydb I/System.out:    rootpage=3
2019-07-04 10:31:11.597 4757-4757/aso.so56873021recopydb I/System.out:    sql=CREATE TABLE android_metadata (locale TEXT)
2019-07-04 10:31:11.597 4757-4757/aso.so56873021recopydb I/System.out: }
2019-07-04 10:31:11.597 4757-4757/aso.so56873021recopydb I/System.out: 1 {
2019-07-04 10:31:11.597 4757-4757/aso.so56873021recopydb I/System.out:    type=table
2019-07-04 10:31:11.597 4757-4757/aso.so56873021recopydb I/System.out:    name=room_master_table

Stage 4

version increased from 1 to 2 :-

07-04 10:38:42.679 8857-8857/? D/DBVERSION: The stored database version is 1
07-04 10:38:42.679 8857-8857/? D/DBCOPY: DB Copy inititaed
07-04 10:38:42.680 8857-8857/? D/DBCOPY: Database copied. 77824 bytes copied.
07-04 10:38:42.680 8857-8857/? D/DB STATUS:: Daatabase Created ----------------
07-04 10:38:42.683 8857-8857/? D/Database Versions:: old:1
    new:2
07-04 10:38:42.688 8857-8857/? I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@f2b3d69
07-04 10:38:42.688 8857-8857/? I/System.out: 0 {
07-04 10:38:42.688 8857-8857/? I/System.out:    type=table
07-04 10:38:42.688 8857-8857/? I/System.out:    name=android_metadata
07-04 10:38:42.688 8857-8857/? I/System.out:    tbl_name=android_metadata
07-04 10:38:42.688 8857-8857/? I/System.out:    rootpage=3
07-04 10:38:42.689 8857-8857/? I/System.out:    sql=CREATE TABLE android_metadata (locale TEXT)
07-04 10:38:42.689 8857-8857/? I/System.out: }
07-04 10:38:42.689 8857-8857/? I/System.out: 1 {
07-04 10:38:42.689 8857-8857/? I/System.out:    type=table
07-04 10:38:42.689 8857-8857/? I/System.out:    name=shops
07-04 10:38:42.689 8857-8857/? I/System.out:    tbl_name=shops
07-04 10:38:42.689 8857-8857/? I/System.out:    rootpage=4
07-04 10:38:42.689 8857-8857/? I/System.out:    sql=CREATE TABLE shops (_id INTEGER  PRIMARY KEY , shoporder INTEGER  DEFAULT 1000 , shopname TEXT , shopstreet TEXT , shopcity TEXT , shopstate TEXT , shopnotes TEXT )
07-04 10:38:42.689 8857-8857/? I/System.out: }
........
  • 注意 76K 已复制,表现在已商店

在 API 28 上:-

2019-07-04 10:40:31.799 5010-5010/aso.so56873021recopydb D/DBVERSION: The stored database version is 1
2019-07-04 10:40:31.800 5010-5010/aso.so56873021recopydb D/DBCOPY: DB Copy inititaed
2019-07-04 10:40:31.802 5010-5010/aso.so56873021recopydb D/DBCOPY: Database copied. 77824 bytes copied.
2019-07-04 10:40:31.802 5010-5010/aso.so56873021recopydb D/DB STATUS:: Daatabase Created ----------------
2019-07-04 10:40:31.826 5010-5010/aso.so56873021recopydb D/Database Versions:: old:1
    new:2
...........

Stage 5

应用程序再次运行(即发布复制已完成):-

07-04 10:41:53.653 8947-8947/? D/DBVERSION: The stored database version is 2
07-04 10:41:53.655 8947-8947/? I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@8c743f0
07-04 10:41:53.655 8947-8947/? I/System.out: 0 {
07-04 10:41:53.655 8947-8947/? I/System.out:    type=table
07-04 10:41:53.655 8947-8947/? I/System.out:    name=android_metadata
07-04 10:41:53.655 8947-8947/? I/System.out:    tbl_name=android_metadata
07-04 10:41:53.655 8947-8947/? I/System.out:    rootpage=3
07-04 10:41:53.655 8947-8947/? I/System.out:    sql=CREATE TABLE android_metadata (locale TEXT)
07-04 10:41:53.655 8947-8947/? I/System.out: }
07-04 10:41:53.655 8947-8947/? I/System.out: 1 {
07-04 10:41:53.655 8947-8947/? I/System.out:    type=table
07-04 10:41:53.655 8947-8947/? I/System.out:    name=shops
07-04 10:41:53.655 8947-8947/? I/System.out:    tbl_name=shops

在 API 28 上:-

2019-07-04 10:42:41.296 5098-5098/aso.so56873021recopydb D/DBVERSION: The stored database version is 2
2019-07-04 10:42:41.306 5098-5098/aso.so56873021recopydb I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@877f345
2019-07-04 10:42:41.307 5098-5098/aso.so56873021recopydb I/System.out: 0 {
2019-07-04 10:42:41.308 5098-5098/aso.so56873021recopydb I/System.out:    type=table
2019-07-04 10:42:41.308 5098-5098/aso.so56873021recopydb I/System.out:    name=android_metadata
2019-07-04 10:42:41.308 5098-5098/aso.so56873021recopydb I/System.out:    tbl_name=android_metadata
2019-07-04 10:42:41.308 5098-5098/aso.so56873021recopydb I/System.out:    rootpage=3
2019-07-04 10:42:41.308 5098-5098/aso.so56873021recopydb I/System.out:    sql=CREATE TABLE android_metadata (locale TEXT)
2019-07-04 10:42:41.308 5098-5098/aso.so56873021recopydb I/System.out: }
2019-07-04 10:42:41.308 5098-5098/aso.so56873021recopydb I/System.out: 1 {
2019-07-04 10:42:41.308 5098-5098/aso.so56873021recopydb I/System.out:    type=table
2019-07-04 10:42:41.308 5098-5098/aso.so56873021recopydb I/System.out:    name=shops
2019-07-04 10:42:41.309 5098-5098/aso.so56873021recopydb I/System.out:    tbl_name=shops
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在我的下一个 Android 应用程序更新中使用新的数据库版本覆盖现有的已发布 Sqlite DB 的相关文章

  • SQL 连接两个没有关系的表

    我有具有相同结构的不同表 我想通过其中一列将它们连接起来 问题是他们不共享该专栏中的信息 Table 1 Type A Name Value Table 2 Type B Name Value 结果表 在单列中 nameFromA name
  • 如何正确释放Android MediaPlayer

    我正在尝试向我的 Android 应用程序添加一个按钮 当点击该按钮时它会播放 MP3 我已经让它工作了 但没有办法释放 mediaPlayer 对象 因此即使在我离开活动后它仍然会继续播放 如果我在react 方法之外初始化MediaPl
  • Recyclerview 动态部分不使用任何第三个库

    我想将标头添加到 recyclerview 我正在尝试使用来实现它 Override public int getItemViewType int position depends on your problem if position 0
  • Android 初学者:Android gridview 中的触摸事件

    我正在使用以下代码来使用 gridview 执行操作 稍作修改http developer android com resources tutorials views hello gridview html http developer a
  • 如何更改终端的默认目录?

    我想更改 Android Studio v2 2 2 终端的默认目录 当我打开终端时 它基于项目的目录 C 项目路径 我经常需要使用adb shell 所以我必须导航到 SDK 路径 平台工具 才能使用 adb 命令 是否可以更改终端的默认
  • Dialog.setTitle 不显示标题

    我正在尝试向我的对话框添加自定义标题 但是每当我运行我的应用程序时 它都不会显示标题 我创建对话框的代码是 final Dialog passwordDialog new Dialog this passwordDialog setCont
  • java.lang.IllegalStateException:应用程序 PagerAdapter 更改了适配器的内容,而没有调用 PagerAdapter#notifyDataSetChanged android

    我正在尝试使用静态类将值传递给视图 而不是使用意图 因为我必须传递大量数据 有时我会收到此错误 但无法找出主要原因是什么 Error java lang IllegalStateException The application s Pag
  • 为什么是 javascript:history.go(-1);无法在移动设备上工作?

    首先 一些背景 我有一个向用户呈现搜索页面 html 表单 的应用程序 填写标准并单击 搜索 按钮后 结果将显示在标准部分下方 在结果列表中 您可以通过单击将您带到新页面的链接来查看单个结果的详细信息 在详细信息页面中 我添加了一个 返回结
  • Android Studio 与本地网络共享上的项目文件

    这是我的设置 Android Studio 项目文件位于 Ubuntu 14 10 盒子上的共享文件夹中 尝试在 Windows 8 机器上运行 Android Studio 1 0 2 并将 U 驱动器映射到包含项目文件的 Ubuntu
  • 当 OnFocusChangeListener 应用于包装的 EditText 时,TextInputLayout 没有动画

    不能比标题说得更清楚了 我有一个由文本输入布局包裹的 EditText 我试图在 EditText 失去焦点时触发一个事件 但是 一旦应用了事件侦听器 TextInputLayout 就不再对文本进行动画处理 它只是位于 editText
  • Mipmap 与可绘制文件夹[重复]

    这个问题在这里已经有答案了 我正在使用 Android Studio 1 1 Preview 1 我注意到 当我创建一个新项目时 我得到以下层次结构 不同 DPI 的 Mipmap 文件夹 不再有不同 DPI 的可绘制文件夹 我应该将所有资
  • Android Studio 缓慢的增量构建

    我已经完成了许多步骤来完善我们的构建系统 those https stackoverflow com questions 16775197 building and running app via gradle and android st
  • Android 中的处理程序与异步调用

    目前我正在使用处理程序来调用 Web 服务方法以使其在后台运行 问题是它需要更多的时间来给出响应 在性能方面似乎更昂贵 现在我计划使用异步调用 哪一个是最好的 Android 中的处理程序和异步调用有什么区别 请帮我想出一个最好的解决方案
  • 如何检查 Android 中的同步设置

    我正在构建一个 Android 应用程序 我需要检查设备中注册的每个单独帐户的同步设置 我知道我可以通过 ContentResolver 类来做到这一点 但我遇到了一些问题 我已设法获取设备上所有帐户的列表 但我不知道在运行时从哪里获取特定
  • 找不到符号 NOTIFICATION_SERVICE?

    package com test app import android app Notification import android app NotificationManager import android app PendingIn
  • 问题:为什么React Native Video不能全屏播放视频?

    我正在react native 0 57 7 中为android和ios创建一个应用程序并使用反应本机视频 https github com react native community react native video播放上传到的视频
  • 没有支持 FEATURE_CAMERA_EXTERNAL 的 Android 设备

    根据this doc https source android com devices camera external usb cameras一些 Android 设备允许使用 Camera2 API 访问外部 USB 摄像头 我检查了大约
  • 如何使用 AccessibilityService 在 Android 中模拟按键

    我正在编写一个辅助服务 我一直在尝试在应用程序上进行一些自动搜索 我使用accessibilityservice action paste来填充EditText 然后我需要模拟软键盘上的按键 但我不知道如何做 你们能帮我一下吗 你可以尝试A
  • Android 后台倒计时器

    我有一个 Android 应用程序 它管理一个倒计时器 类 CountDownTimer 它显示在应用程序屏幕中 以显示到达 00 00 还剩多少时间 我现在的问题是 当我按主页按钮或启动另一个应用程序时 应用程序 计时器不会在后台运行 所
  • Android 屏幕方向错误

    我使用的是 Android HTC HERO 2 1 版本 我写的活动

随机推荐

  • 如何修改继续时的 Step StepState

    我正在关注这个教程https www youtube com watch v izbkS2svuq4 https www youtube com watch v izbkS2svuq4 并简要提到将 StepState 修改为 StepSt
  • Silex 设置 cookie

    我正在使用 Silex Framework 并且我正在拼命尝试设置 cookie 文档中找不到任何信息 我几乎尝试了所有方法 有人可能有这方面的经验 并且可以提供一个小例子吗 Thanks 以下是我的一个网站的摘录 该网站设置了 cooki
  • 如何使用命名管道从 C++ 调用 WCF 方法?

    更新 查看协议here http msdn microsoft com en us library cc219293 28v PROT 10 29 aspx 我不知道 Unsized Envelope Record 中会包含什么内容 我在网
  • 如何动态创建

    我想在我的网络表单中动态创建输入类型文本 更具体地说 我有一个文本字段 用户可以在其中输入所需文本字段的数量 我希望以相同的形式动态生成文本字段 我怎么做 使用 JavaScript var input document createEle
  • 通过超链接打开新的gridview

    如何通过同一页面上的超链接打开一个新的 gridview 当用户单击此表上的任何超链接时 我不想关闭现有的 gridview 而是想显示与此相邻的另一个 gridview 我有一些如下所示的数据 当我单击这些超链接中的任何一个时 我想在同一
  • 如何递归地忽略 git 存储库中的所有隐藏目录/文件?

    我想让 Git 忽略所有隐藏的文件和目录 IE aptitude ssh bash rc config hidden 是否有一个简单的规则可以涵盖这个问题而无需专门添加每个条目 只需添加一个图案即可 gitignore gitignore
  • REST 和大型数据库查询

    众所周知 ReST Web 服务无法保存状态 当我考虑大型数据库事务时 这对我来说是一个问题 我想知道您是否可以提供帮助 我的 ReST Web 服务有一个主要作用 对数据库执行 CRUD 操作 问题是 如果我必须查询包含数千行的表并将其作
  • 使用 JavaScript 添加外部样式表

    我需要使用外部 javascript 文件在标头中添加指向外部 css 文件的链接 不要问为什么 我只需要这样做 document write 顺便说一句 不起作用 var element document createElement li
  • 如何在文本上应用 CSS 渐变(从透明颜色到不透明颜色)

    Cheers 我是 CSS HTML 的新手 但我想在文本上应用渐变 如下图所示 我如何用css来实现它 相关CSS在伪元素上 after of the
  • jquery 与相同脚本冲突

    我正在使用 jquery 将内容加载到选项卡中 并在单击时切换选项卡 我的问题是 我在一页中使用了这个 选项卡切换器 两次 并且它导致了冲突 我对jquery不太有经验 所以我的问题可能在于我在头脑中创建了两次函数 这是我的 jquery
  • ST_Buffer 相当于 MySQL 中基于圆的搜索吗?

    我需要使用 MySQL GIS 搜索具有指定圆内的点的行 伪代码示例查询是 select from gistable g where isInCircle g point circleCenterPT radius 看来 PostGIS 可
  • AWS ELB(弹性负载均衡器)有时会立即返回 504(网关超时)

    我目前正在将应用程序切换到亚马逊 但我注意到有时收到的响应是 504 我们的系统设置方式是在 ELB 前面有一个 LB 然后直接转到 tomcat 目前 我们正在对服务中的所有请求以及记录响应时间的 servlet 过滤器进行计时 它们始终
  • Zip Mime 类型无法识别

    我正在尝试返回一个 zip 文件 作为浏览器上的流 这适用于其他类型的文件 例如 Excel 文件 但是当我开始处理 zip 文件时 我无法让浏览器识别出它是 zip 我的测试机上运行的 Firefox 和 IE 都会提示 询问使用什么程序
  • Python UCS2 从十六进制字符串解码

    我正在使用 python 2 7 需要将十六进制字符串解码为 un icode 字符串 在 php 中 我做了以下简单的操作 line hex2bin line finish iconv UCS 2BE UTF 8 nline 例如十六进制
  • 我可以在 android xml 布局或字符串值文件中编写 java 代码吗?

    我想知道是否可以在 android XML 布局或字符串值文件中编写 java 代码 我的意思是这样的
  • 给定3个点,如何构造穿过它们的弧?

    假设我有 3 个连续点 P1 P2 P3 如何构造一条经过所有3个点的弧 弧必须具有以下 3 个属性 开始弧度 结束弧度 中心点 弧线是从Start Radian to End Radian以逆时针方向 我已经尝试过解决方案here htt
  • 东向北转纬度经度

    我有东向 北向格式的位置坐标 但我需要将其转换为正确的经纬度 以使其在 bing 地图中居中 有任何公式或详细信息如何将东距 北距转换为纬度 经度吗 编辑 更具体地说 我需要将 SVY21 坐标转换为 WGS84 东距和北距分别是基点向东和
  • EMR-5.32.0 上的 Spark 未生成请求的执行程序

    我在 EMR 版本 5 32 0 上的 Py Spark 中遇到了一些问题 大约一年前 我在 EMR 集群上运行了相同的程序 我认为版本一定是 5 29 0 然后我可以使用配置我的 PySpark 程序spark submit正确地论证 但
  • 正在验证 MVC 隐藏字段

    我的页面上有一些字段 它们的显示和消失取决于您在页面上所做的下拉选择 所以 举例来说 我有 section Html LabelFor model gt model AuctionTypeId div Html DropDownList A
  • 在我的下一个 Android 应用程序更新中使用新的数据库版本覆盖现有的已发布 Sqlite DB

    我想覆盖旧应用程序版本附带的现有数据库 并在下一个应用程序更新中使用新完全填充的数据库 然而 onUpgrade 永远不会被调用 尽管我尝试在将 DB version 传递给 SQLiteOpenHelper 类时更改它 public cl