Sharing Application Data Between Two Android Apps – Part II

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.internalfile_allow_sharing;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends Activity {
private EditText txtData;
private Button btnWriteISDFile, btnReadISDFile, btnClearScreen,
btnDeleteSDFile;
private static final String fileName = "DemoTextFile.txt";

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

txtData = (EditText) findViewById(R.id.txtData);
txtData.setHint("Enter some lines of data here...");

btnWriteISDFile = (Button) findViewById(R.id.btnWriteISDFile);
btnWriteISDFile.setOnClickListener(new OnClickListener() {

public void onClick(View v) {
try {
FileOutputStream fOut = openFileOutput(fileName,
MODE_PRIVATE);
OutputStreamWriter myOutWriter = new OutputStreamWriter(
fOut);
myOutWriter.append(txtData.getText());
myOutWriter.close();
fOut.close();
Toast.makeText(getBaseContext(),
"Done writing file- 'DemoTextFile.txt'",
Toast.LENGTH_SHORT).show();
} catch (Exception e) {
Toast.makeText(getBaseContext(), e.getMessage(),
Toast.LENGTH_SHORT).show();
}

}
});

btnReadISDFile = (Button) findViewById(R.id.btnReadISDFile);
btnReadISDFile.setOnClickListener(new OnClickListener() {

public void onClick(View v) {
try {
FileInputStream fIn = openFileInput(fileName);
BufferedReader myReader = new BufferedReader(
new InputStreamReader(fIn));
String aDataRow = "";
String aBuffer = "";
while ((aDataRow = myReader.readLine()) != null) {
aBuffer += aDataRow + "\n";
}
txtData.setText(aBuffer);
myReader.close();
Toast.makeText(getBaseContext(),
"Done reading file- 'DemoTextFile.txt'",
Toast.LENGTH_SHORT).show();
} catch (Exception e) {
Toast.makeText(getBaseContext(), e.getMessage(),
Toast.LENGTH_SHORT).show();
}
}
});

btnClearScreen = (Button) findViewById(R.id.btnClearScreen);
btnClearScreen.setOnClickListener(new OnClickListener() {

public void onClick(View v) {
txtData.setText("");
}
});

btnDeleteSDFile = (Button) findViewById(R.id.btnDeleteISDFile);
btnDeleteSDFile.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
// TODO Auto-generated method stub
File file = new File(MainActivity.this.getFilesDir(), fileName);
boolean deleted = file.delete();
if (deleted) {
Toast.makeText(getBaseContext(),
"File Deleted Sucessfully", Toast.LENGTH_SHORT)
.show();
} else {
Toast.makeText(getBaseContext(), "File Not Found",
Toast.LENGTH_SHORT).show();
}
}
});
}

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

Step 2: Open your 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.internalfile_allow_sharing.MainActivity" >

<EditText
android:id="@+id/txtData"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/btnReadISDFile"
android:layout_alignParentTop="true"
android:textSize="18sp" />

<Button
android:id="@+id/btnReadISDFile"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginBottom="55dp"
android:text="Read File" />

<Button
android:id="@+id/btnWriteISDFile"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/txtData"
android:layout_alignRight="@+id/btnClearScreen"
android:layout_alignTop="@+id/btnReadISDFile"
android:text="Write File" />

<Button
android:id="@+id/btnClearScreen"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/btnWriteISDFile"
android:text="Clear Screen" />

<Button
android:id="@+id/btnDeleteISDFile"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/btnClearScreen"
android:layout_alignBottom="@+id/btnClearScreen"
android:layout_alignRight="@+id/btnReadISDFile"
android:text="Delete File" />

</RelativeLayout>

Step 3: Open 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.internalfile_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 4: 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.internalfile_reader_sharing;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

import android.app.Activity;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends Activity {
private EditText txtData;
private Button btnWriteISDFile, btnReadISDFile, btnClearScreen,
btnDeleteISDFile;
private static final String filePath = "/files/DemoTextFile.txt";
String packageName = "com.skholingua.android.internalfile_allow_sharing";
ApplicationInfo apInfo ;
String fileFullPath;
private static final String fileName = "DemoTextFile.txt";

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

txtData = (EditText) findViewById(R.id.txtData);
txtData.setHint("Enter some lines of data here...");

PackageManager packageManager = getPackageManager();
try {
apInfo = packageManager.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
} catch (NameNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}

fileFullPath = apInfo.dataDir + filePath;

btnReadISDFile = (Button) findViewById(R.id.btnReadISDFile);
btnReadISDFile.setOnClickListener(new OnClickListener() {

public void onClick(View v) {
try {
FileInputStream fIn = new FileInputStream(new File(fileFullPath));
BufferedReader myReader = new BufferedReader(
new InputStreamReader(fIn));
String aDataRow = "";
String aBuffer = "";
while ((aDataRow = myReader.readLine()) != null) {
aBuffer += aDataRow + "\n";
}
txtData.setText(aBuffer);
myReader.close();
Toast.makeText(getBaseContext(),
"Done reading file- 'DemoTextFile.txt'",
Toast.LENGTH_SHORT).show();
} catch (Exception e) {
Toast.makeText(getBaseContext(), e.getMessage(),
Toast.LENGTH_SHORT).show();
}
}
});

btnClearScreen = (Button) findViewById(R.id.btnClearScreen);
btnClearScreen.setOnClickListener(new OnClickListener() {

public void onClick(View v) {
txtData.setText("");
}
});

btnWriteISDFile = (Button) findViewById(R.id.btnWriteISDFile);
btnWriteISDFile.setOnClickListener(new OnClickListener() {

public void onClick(View v) {
try {
FileOutputStream fOut = openFileOutput(fileName,
MODE_PRIVATE);
OutputStreamWriter myOutWriter = new OutputStreamWriter(
fOut);
myOutWriter.append(txtData.getText());
myOutWriter.close();
fOut.close();
Toast.makeText(getBaseContext(),
"Done writing file- 'DemoTextFile.txt'",
Toast.LENGTH_SHORT).show();
} catch (Exception e) {
Toast.makeText(getBaseContext(), e.getMessage(),
Toast.LENGTH_SHORT).show();
}

}
});
btnDeleteISDFile = (Button) findViewById(R.id.btnDeleteISDFile);
btnDeleteISDFile.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
// TODO Auto-generated method stub
File file = new File(MainActivity.this.getFilesDir(), fileName);
boolean deleted = file.delete();
if (deleted) {
Toast.makeText(getBaseContext(),
"File Deleted Sucessfully", Toast.LENGTH_SHORT)
.show();
} else {
Toast.makeText(getBaseContext(), "File Not Found",
Toast.LENGTH_SHORT).show();
}
}
});

}

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

Step 6: 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.internalfile_reader_sharing.MainActivity" >

<EditText
android:id="@+id/txtData"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/btnReadISDFile"
android:layout_alignParentTop="true"
android:textSize="18sp" />

<Button
android:id="@+id/btnReadISDFile"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginBottom="55dp"
android:text="Read File" />

<Button
android:id="@+id/btnWriteISDFile"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/txtData"
android:layout_alignRight="@+id/btnClearScreen"
android:layout_alignTop="@+id/btnReadISDFile"
android:text="Write File" />

<Button
android:id="@+id/btnClearScreen"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/btnWriteISDFile"
android:text="Clear Screen" />

<Button
android:id="@+id/btnDeleteISDFile"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/btnClearScreen"
android:layout_alignBottom="@+id/btnClearScreen"
android:layout_alignRight="@+id/btnReadISDFile"
android:text="Delete File" />

</RelativeLayout>

Step 7: Open AndroidManifest.xml and copy this code:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.skholingua.android.internalfile_reader_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>

ScreenShots:

Screenshot_2015-04-06-08-37-18 Screenshot_2015-04-06-08-40-11 Screenshot_2015-04-06-08-40-27 Screenshot_2015-04-06-08-40-35


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, Otherthan like Sharepreferences, here we don’t context of the application, but rather we need application path of that file location. So i’m using Application PackageManager to get information about that application and from that we are getting it’s Directory location for use.
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 *