How to share the same SQLiteDatabase between two Android apps

According to Android developer website, “Any databases you create will be accessible by name to any class in the application, but not outside the application.” So the database is private to the application.

But what if we need to share the same data between two different apps? This tutorial will explain how it is done.

By default the SQLite databases are created in /data/data/[packagename]/databases directory. This is private to the app, so other apps cannot access this. But since we need to share the database between two apps we need to create the database in the primary external storage directory.

File dbFile = new File(Environment.getExternalStorageDirectory()+"/testdb.db");
SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(dbFile, null);
db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE + " (" +
ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + 
DATA + " INTEGER" + ");");

I create two simple apps to demonstrate this. You can download the two Android projects here.

So in both apps we need to open the database using the above code.  Then we can use the db instance to save and retrieve data.

	public void saveData(int data, SQLiteDatabase db) {
		ContentValues contentValues = new ContentValues();
		contentValues.put(DATA, data);	
		long id = db.insert(TABLE, null, contentValues);
		Log.i(TAG, "::saveData: id = " + id + " data = "+data);
	}
	
	public void getAllData(SQLiteDatabase db) {
		try {
			Cursor cursor = db.query(TABLE,
					new String[] { 
					ID, 
					DATA
			}, null, null, null, null, ID);

			if (cursor != null) {
				if (cursor.moveToFirst()) {
					do {
						int colIndex = cursor.getColumnIndex(ID);
						int id = cursor.getInt(colIndex);
						colIndex = cursor.getColumnIndex(DATA);
						int data = cursor.getInt(colIndex);
						Log.i(TAG, "::getAllData: id = "+id+" data = " + data);
					} while (cursor.moveToNext());
				}
				cursor.close();
			}
		} catch (SQLiteException e) {
			e.printStackTrace();
		}
	}
	

In our demo app we have two buttons. Add button will add some data. And Get button will get all the data.

	@Override
	public void onClick(View v) {
		switch(v.getId()){
		case R.id.btn_add:
			saveData(new Random().nextInt(5) * 10, db);
			break;
		case R.id.btn_query:
			getAllData(db);
			break;
		}		
	}
	

Then lets run the DemoApp1 and store some data in the database.  The logcat will show the following.

06-03 15:38:13.411: I/sqlitedemo1(14459): ::saveData: id = 1 data = 30
06-03 15:38:14.001: I/sqlitedemo1(14459): ::saveData: id = 2 data = 10
06-03 15:38:14.551: I/sqlitedemo1(14459): ::saveData: id = 3 data = 40
06-03 15:38:15.081: I/sqlitedemo1(14459): ::saveData: id = 4 data = 0
06-03 15:38:15.601: I/sqlitedemo1(14459): ::saveData: id = 5 data = 0

Then run the DemoApp2 and click Get.
06-03 15:38:35.721: I/sqlitedemo2(14740): ::getAllData: id = 1 data = 30
06-03 15:38:35.721: I/sqlitedemo2(14740): ::getAllData: id = 2 data = 10
06-03 15:38:35.721: I/sqlitedemo2(14740): ::getAllData: id = 3 data = 40
06-03 15:38:35.721: I/sqlitedemo2(14740): ::getAllData: id = 4 data = 0
06-03 15:38:35.721: I/sqlitedemo2(14740): ::getAllData: id = 5 data = 0

Add some more data from DemoApp2,
06-03 15:43:03.411: I/sqlitedemo2(14740): ::saveData: id = 6 data = 0
06-03 15:43:03.681: I/sqlitedemo2(14740): ::saveData: id = 7 data = 10
06-03 15:43:04.071: I/sqlitedemo2(14740): ::saveData: id = 8 data = 30

And go back to DemoApp1 and click Get,
06-03 15:44:12.421: I/sqlitedemo1(14459): ::getAllData: id = 1 data = 30
06-03 15:44:12.421: I/sqlitedemo1(14459): ::getAllData: id = 2 data = 10
06-03 15:44:12.421: I/sqlitedemo1(14459): ::getAllData: id = 3 data = 40
06-03 15:44:12.421: I/sqlitedemo1(14459): ::getAllData: id = 4 data = 0
06-03 15:44:12.421: I/sqlitedemo1(14459): ::getAllData: id = 5 data = 0
06-03 15:44:12.421: I/sqlitedemo1(14459): ::getAllData: id = 6 data = 0
06-03 15:44:12.421: I/sqlitedemo1(14459): ::getAllData: id = 7 data = 10
06-03 15:44:12.421: I/sqlitedemo1(14459): ::getAllData: id = 8 data = 30

You can see that both apps can read and write data to the shared database.