Sharing Application Data Between Two Android Apps – Part III

In this blog post, i’ll show you How to share one Application data with one or many Application you need, the data’s can be SharedPreferences data, InternalStorage files and Local Database too.

Why one need to Share its Application data for another? – Some times when your developing Application for both free and paid application, then sharing data between apps will be more useful and for games, this will be used by many developers.

To achieve this, one should know What is Appication UserID?

At install time, Android gives each package a distinct Linux user ID. The name of a Linux user ID that will be shared with other applications. By default, Android assigns each application its own unique user ID. However, if this attribute is set to the same value for two or more applications, they will all share the same ID — provided that they are also signed by the same certificate. Application with the same user ID can access each other’s data and, if desired, run in the same process. for more details read here.

so, when developing applications, use same userId , in the app manifest.


android:sharedUserId="string"

android:sharedUserLabel="string resource"

sharedUserLabel is a user-readable label for the shared user ID. The label must be set as a reference to a string resource; it cannot be a raw string.

 

To Demonstrate this, we need to develop two Application for each. So this gonna be a massive tutorial and lets get started.

To make this simple, i have made 3 blog post including this.

My Other blog post on Sharing Application Data Between Apps.

  1. Part I – Sharing SharedPreferences data
  2. Part II – Sharing InternalStorage File’s
  3. Part III – Sharing Local DataBase(unofficial or undocumented method)
  4. Part IV – using ContentProvider (recommended by Android Developers)

 

1st Application :

Step 1: Create a new project File -> Android Project. While creating a new project give activity name as MainActivity and copy paste this code.


package com.skholingua.android.database_allow_sharing;

import java.util.List;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ArrayAdapter;
import android.widget.ListView;

public class MainActivity extends Activity {
private SqlLiteManger _sqlLiteManger;
private List<String> _listFromDB;
private ArrayAdapter<String> _adapter;
private ListView listView;

private String[] _versionName = { "Eclair", "Froyo", "Gingerbread",
"HoneyComb", "Ice-cream Sandwich", "JellyBean", "KitKat",
"LolliPop" };
private String[] _versionNo = { "2.0 - 2.1", "2.2 - 2.2.3", "2.3 - 2.3.7",
"3.0 - 3.2.6", "4.0 - 4.0.4", "4.1 - 4.3.1", "4.4 - 4.4.4", "5.0" };

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) findViewById(R.id.listView1);

_sqlLiteManger = new SqlLiteManger(this);
_sqlLiteManger.open();

for (int i = 0; i < _versionName.length; i++) {
_sqlLiteManger.insert(_versionName[i], _versionNo[i]);
}

_listFromDB = _sqlLiteManger.fetch();
_adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, _listFromDB);
listView.setAdapter(_adapter);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}

//    @Override
//    protected void onDestroy() {
//        // TODO Auto-generated method stub
//        super.onDestroy();
//        _sqlLiteManger.truncateTable();
//        _sqlLiteManger.close();
//    }
}

 

Step 2: open activity_main.xml and copy this code:


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.skholingua.android.database_allow_sharing.MainActivity" >

<ListView
android:id="@+id/listView1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true" >
</ListView>

</RelativeLayout>


Step 3: Create new class, SqlLiteDbHelper.java and copy paste this code :

package com.skholingua.android.database_allow_sharing;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class SqlLiteDbHelper extends SQLiteOpenHelper {

    // Table Name
    public static final String TABLE_NAME = "ANDROID_OS_LIST";

    // Table columns
    public static final String _ID = "_id";
    public static final String VERSION_NAME = "version_name";
    public static final String VERSION_NO = "version_no";

    // Database Information
    static final String DB_NAME = "android_os.db";

    // database version
    static final int DB_VERSION = 1;

    // Creating table query
    private static final String CREATE_TABLE = "create table " + TABLE_NAME
            + "(" + _ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + VERSION_NAME
            + " TEXT, " + VERSION_NO + " TEXT);";

    public SqlLiteDbHelper(Context context) {
        super(context, DB_NAME, null, DB_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(CREATE_TABLE);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
        onCreate(db);
    }
}

Step 4: create new class, SqlLiteManger.java and copy paste this code:

package com.skholingua.android.database_allow_sharing;

import java.util.ArrayList;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;

public class SqlLiteManger {

    private SqlLiteDbHelper _dbHelper;

    private Context context;

    private SQLiteDatabase database;

    public SqlLiteManger(Context c) {
        context = c;
        _dbHelper = new SqlLiteDbHelper(context);
    }

    public SqlLiteManger open() throws SQLException {

        database = _dbHelper.getWritableDatabase();
        return this;
    }

    public void close() {
        _dbHelper.close();
    }

    public void insert(String name, String version) {
        database.beginTransaction();
        try {
            ContentValues contentValue = new ContentValues();
            contentValue.put(SqlLiteDbHelper.VERSION_NAME, name);
            contentValue.put(SqlLiteDbHelper.VERSION_NO, version);
            database.insert(SqlLiteDbHelper.TABLE_NAME, null, contentValue);
            database.setTransactionSuccessful();
        } finally {
            database.endTransaction();
        }
    }

    public ArrayList<String> fetch() {
        ArrayList<String> list = new ArrayList<>();
        String[] columns = new String[] { SqlLiteDbHelper._ID,
                SqlLiteDbHelper.VERSION_NAME, SqlLiteDbHelper.VERSION_NO };
        Cursor cursor = database.query(SqlLiteDbHelper.TABLE_NAME, columns,
                null, null, null, null, null);
        if (cursor != null & cursor.moveToFirst()) {
            do {
                String _versionName = cursor.getString(cursor
                        .getColumnIndex(SqlLiteDbHelper.VERSION_NAME));
                String _versionNo = cursor.getString(cursor
                        .getColumnIndex(SqlLiteDbHelper.VERSION_NO));
                list.add("Version Name : " + _versionName + ",\nVersion No: "
                        + _versionNo);
            } while (cursor.moveToNext());
        }
        return list;
    }

    public void truncateTable() {
        database.delete(SqlLiteDbHelper.TABLE_NAME, null, null);
    }
}

 

 

Step 5: Open your AndroidManifest.xml and copy paste this code.


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.skholingua.android.database_allow_sharing"
android:versionCode="1"
android:versionName="1.0"
android:sharedUserId="skholingua" >

<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="19" />

<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>

2nd Application :
Step 1: Create a new project File -&amp;amp;amp;gt; Android Project. While creating a new project give activity name as MainActivity and copy paste this code.


package com.skholingua.android.database_reader_shared_db;

import java.util.List;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ArrayAdapter;
import android.widget.ListView;

public class MainActivity extends Activity {
private SqlLiteManger _sqlLiteManger;
private List<String> _listFromDB;
private ArrayAdapter<String> _adapter;
private ListView listView;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

Context sharedContext = null;
try {
sharedContext = this.createPackageContext(
"com.skholingua.android.database_allow_sharing",
Context.CONTEXT_INCLUDE_CODE);
if (sharedContext == null) {
return;
}
} catch (Exception e) {
String error = e.getMessage();
System.out.println("DB error : " + error);
return;
}

_sqlLiteManger = new SqlLiteManger(sharedContext);
_sqlLiteManger.open();
listView = (ListView) findViewById(R.id.listView1);
_listFromDB = _sqlLiteManger.fetch();
_adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, _listFromDB);
listView.setAdapter(_adapter);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}

@Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
_sqlLiteManger.truncateTable();
_sqlLiteManger.close();
}
}

Step 2: Open activity_main.xml and copy paste this code:


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.skholingua.android.database_reader_shared_db.MainActivity" >

<ListView
android:id="@+id/listView1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true" >
</ListView>
</RelativeLayout>


Step 3. create new class, SqlLiteDbHelper.java and copy paste this code:


package com.skholingua.android.database_reader_shared_db;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class SqlLiteDbHelper extends SQLiteOpenHelper {

// Table Name
public static final String TABLE_NAME = "ANDROID_OS_LIST";

// Table columns
public static final String _ID = "_id";
public static final String VERSION_NAME = "version_name";
public static final String VERSION_NO = "version_no";

// Database Information
static final String DB_NAME = "android_os.db";

// database version
static final int DB_VERSION = 1;

public SqlLiteDbHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}

@Override
public void onCreate(SQLiteDatabase db) {
}

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

}

Step 4. create new class, SqlLiteManger.java and copy paste this code:


package com.skholingua.android.database_reader_shared_db;

import java.util.ArrayList;

import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;

public class SqlLiteManger {

private SqlLiteDbHelper _dbHelper;

private Context context;

private SQLiteDatabase database;

public SqlLiteManger(Context c) {
context = c;
_dbHelper = new SqlLiteDbHelper(context);
}

public SqlLiteManger open() throws SQLException {

database = _dbHelper.getWritableDatabase();
return this;
}

public void close() {
_dbHelper.close();
}

public ArrayList<String> fetch() {
ArrayList<String> list = new ArrayList<>();
String[] columns = new String[] { SqlLiteDbHelper._ID,
SqlLiteDbHelper.VERSION_NAME, SqlLiteDbHelper.VERSION_NO };
Cursor cursor = database.query(SqlLiteDbHelper.TABLE_NAME, columns,
null, null, null, null, null);
if (cursor != null & cursor.moveToFirst()) {
do {
String _versionName = cursor.getString(cursor
.getColumnIndex(SqlLiteDbHelper.VERSION_NAME));
String _versionNo = cursor.getString(cursor
.getColumnIndex(SqlLiteDbHelper.VERSION_NO));
list.add("Version Name : " + _versionName + ",\nVersion No: "
+ _versionNo);
} while (cursor.moveToNext());
}
return list;
}

public void truncateTable() {
database.delete(SqlLiteDbHelper.TABLE_NAME, null, null);
}
}

 

Step 5: Open your AndroidManifest.xml and copy paste this code.


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.skholingua.android.database_reader_shared_db"
android:versionCode="1"
android:versionName="1.0"
android:sharedUserId="skholingua" >

<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="19" />

<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>


ScreenShot:

 Screenshot_2015-04-06-08-34-12 Screenshot_2015-04-06-08-34-26


Tips to Remember always:

1. The String the sharedUserId is not the actual AppUserID and AppUserID is actually be in numbers, so this is just references to the AppUserID.
2. To make this actually work, we also need one more thing along with sharedUserId is both the application should be in same certificate i.e., both apps must compile with the same keystore
3. Last but not the least, we need context of that application to use. So, i’m using createPackageContext) to get the context of that application.
4. Remember if you using this many application sharing data, then this slow down the application process and chances to corrupt data, if you not handling it.


Hope this helpful. Your valuable comments are always welcomed. It will help to improve my post and understanding.

Download Source Code from here.

durga chiranjeevi

durga chiranjeevi

I'm currently working as Android developer at Energy Alternatives India. Interested in Application and Game development.
durga chiranjeevi

Leave a Reply

Your email address will not be published. Required fields are marked *