Saturday, October 22, 2011

Listen SMS-MMS Programmatically Android (Store SMS-MMS Data)

after many hours overtime i got solve this puzzle.. how can we store the incoming (sms/mms) and outgoing (sms/mms) data programmatically?.

MainActivity.java

  
package Com.rdc.listenSmsMms;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;

public class MainActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Log.v("In on create", "activty started..");

//start the service to listen
startService(new Intent(getBaseContext(),ListenSmsMmsService.class));
}
}

ListenSmsMmsService.java
  
package Com.rdc.listenSmsMms;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.Date;

import android.app.Service;
import android.content.ContentResolver;
import android.content.Intent;
import android.database.ContentObserver;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;

public class ListenSmsMmsService extends Service {

private ContentResolver contentResolver;


String substr;
int k;

@Override
public IBinder onBind(Intent intent) {
return null;
}

@Override
public void onCreate() {
Log.v("Debug", " service creatd.........");
}

public void registerObserver() {

contentResolver = getContentResolver();
contentResolver.registerContentObserver(
Uri.parse("content://mms-sms/conversations/"),
true, new SMSObserver(new Handler()));
Log.v("Debug", " in registerObserver method.........");
}

//start the service and register observer for lifetime
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.v("Debug", "Service has been started..");
Toast.makeText(getApplicationContext(),
"Service has been started.. ",
Toast.LENGTH_SHORT).show();
registerObserver();

return START_STICKY;
}

class SMSObserver extends ContentObserver{

public SMSObserver(Handler handler) {
super(handler);
}

//will be called when database get change
@Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
Log.v("Debug", "Observer has been started..");

/*first of all we need to decide message is Text or MMS type.*/
final String[] projection = new String[]{
"_id", "ct_t"};
Uri mainUri = Uri.parse(
"content://mms-sms/conversations/");
Cursor mainCursor = contentResolver.
query(mainUri, projection,
null, null, null);
mainCursor.moveToFirst();

String msgContentType = mainCursor.getString(mainCursor.
getColumnIndex("ct_t"));
if ("application/vnd.wap.multipart.related".
equals(msgContentType)) {
// it's MMS
Log.v("Debug", "it's MMS");

//now we need to decide MMS message is sent or received
Uri mUri = Uri.parse("content://mms");
Cursor mCursor = contentResolver.query(mUri, null, null,
null, null);
mCursor.moveToNext();
int type = mCursor.getInt(mCursor.getColumnIndex("type"));

if(type==1){
//it's received MMS
Log.v("Debug", "it's received MMS");
getReceivedMMSinfo();
}
else if(type==2)
{
//it's sent MMS
Log.v("Debug", "it's Sent MMS");
getSentMMSinfo();
}

}
else{
// it's SMS
Log.v("Debug", "it's SMS");

//now we need to decide SMS message is sent or received
Uri mUri = Uri.parse("content://sms");
Cursor mCursor = contentResolver.query(mUri, null, null,
null, null);
mCursor.moveToNext();
int type = mCursor.getInt(mCursor.getColumnIndex("type"));

if(type==1){
//it's received SMS
Log.v("Debug", "it's received SMS");
getReceivedSMSinfo();
}
else if(type==2)
{
//it's sent SMS
Log.v("Debug", "it's sent SMS");
getSentSMSinfo();
}
}//message content type block closed


}//on changed closed


/*now Methods start to getting details for sent-received SMS*/



//method to get details about received SMS..........
private void getReceivedSMSinfo() {
Uri uri = Uri.parse("content://sms/inbox");
String str = "";
Cursor cursor = contentResolver.query(uri, null,
null,null, null);
cursor.moveToNext();

// 1 = Received, etc.
int type = cursor.getInt(cursor.
getColumnIndex("type"));
String msg_id= cursor.getString(cursor.
getColumnIndex("_id"));
String phone = cursor.getString(cursor.
getColumnIndex("address"));
String dateVal = cursor.getString(cursor.
getColumnIndex("date"));
String body = cursor.getString(cursor.
getColumnIndex("body"));
Date date = new Date(Long.valueOf(dateVal));

str = "Received SMS: \n phone is: " + phone;
str +="\n SMS type is: "+type;
str +="\n SMS time stamp is:"+date;
str +="\n SMS body is: "+body;
str +="\n id is : "+msg_id;


Log.v("Debug","Received SMS phone is: "+phone);
Log.v("Debug","SMS type is: "+type);
Log.v("Debug","SMS time stamp is:"+date);
Log.v("Debug","SMS body is: "+body);
Log.v("Debug","SMS id is: "+msg_id);

Toast.makeText(getBaseContext(), str,
Toast.LENGTH_SHORT).show();
Log.v("Debug", "RDC : So we got all informaion " +
"about SMS Received Message :) ");

}

//method to get details about Sent SMS...........
private void getSentSMSinfo() {
Uri uri = Uri.parse("content://sms/sent");
String str = "";
Cursor cursor = contentResolver.query(uri, null,
null, null, null);
cursor.moveToNext();

// 2 = sent, etc.
int type = cursor.getInt(cursor.
getColumnIndex("type"));
String msg_id= cursor.getString(cursor.
getColumnIndex("_id"));
String phone = cursor.getString(cursor.
getColumnIndex("address"));
String dateVal = cursor.getString(cursor.
getColumnIndex("date"));
String body = cursor.getString(cursor.
getColumnIndex("body"));
Date date = new Date(Long.valueOf(dateVal));

str = "Sent SMS: \n phone is: " + phone;
str +="\n SMS type is: "+type;
str +="\n SMS time stamp is:"+date;
str +="\n SMS body is: "+body;
str +="\n id is : "+msg_id;


Log.v("Debug","sent SMS phone is: "+phone);
Log.v("Debug","SMS type is: "+type);
Log.v("Debug","SMS time stamp is:"+date);
Log.v("Debug","SMS body is: "+body);
Log.v("Debug","SMS id is: "+msg_id);

Toast.makeText(getBaseContext(), str,
Toast.LENGTH_SHORT).show();
Log.v("Debug", "RDC : So we got all informaion " +
"about Sent SMS Message :) ");
}


/*now Methods start to getting details for sent-received MMS.*/

// 1. method to get details about Received (inbox) MMS...
private void getReceivedMMSinfo() {
Uri uri = Uri.parse("content://mms/inbox");
String str = "";
Cursor cursor = getContentResolver().query(uri, null,null,
null, null);
cursor.moveToNext();

String mms_id= cursor.getString(cursor.
getColumnIndex("_id"));
String phone = cursor.getString(cursor.
getColumnIndex("address"));
String dateVal = cursor.getString(cursor.
getColumnIndex("date"));
Date date = new Date(Long.valueOf(dateVal));

// 2 = sent, etc.
int mtype = cursor.getInt(cursor.
getColumnIndex("type"));
String body="";

Bitmap bitmap;

String type = cursor.getString(cursor.
getColumnIndex("ct"));
if ("text/plain".equals(type)){
String data = cursor.getString(cursor.
getColumnIndex("body"));
if(data != null){
body = getReceivedMmsText(mms_id);
}
else {
body = cursor.getString(cursor.
getColumnIndex("text"));
//body text is stored here
}
}
else if("image/jpeg".equals(type) ||
"image/bmp".equals(type) ||
"image/gif".equals(type) ||
"image/jpg".equals(type) ||
"image/png".equals(type)){
bitmap = getReceivedMmsImage(mms_id);
//image is stored here
//now we are storing on SDcard
storeMmsImageOnSDcard(bitmap);
}

str = "Sent MMS: \n phone is: " + phone;
str +="\n MMS type is: "+mtype;
str +="\n MMS time stamp is:"+date;
str +="\n MMS body is: "+body;
str +="\n id is : "+mms_id;


Log.v("Debug","sent MMS phone is: "+phone);
Log.v("Debug","MMS type is: "+mtype);
Log.v("Debug","MMS time stamp is:"+date);
Log.v("Debug","MMS body is: "+body);
Log.v("Debug","MMS id is: "+mms_id);

Toast.makeText(getBaseContext(), str,
Toast.LENGTH_SHORT).show();
Log.v("Debug", "RDC : So we got all informaion " +
"about Received MMS Message :) ");
}




//method to get Text body from Received MMS.........
private String getReceivedMmsText(String id) {
Uri partURI = Uri.parse("content://mms/inbox" + id);
InputStream is = null;
StringBuilder sb = new StringBuilder();
try {
is = getContentResolver().openInputStream(partURI);
if (is != null) {
InputStreamReader isr = new InputStreamReader(is,
"UTF-8");
BufferedReader reader = new BufferedReader(isr);
String temp = reader.readLine();
while (temp != null) {
sb.append(temp);
temp = reader.readLine();
}
}
} catch (IOException e) {}
finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {}
}
}
return sb.toString();
}

//method to get image from Received MMS..............
private Bitmap getReceivedMmsImage(String id) {


Uri partURI = Uri.parse("content://mms/inbox" + id);
InputStream is = null;
Bitmap bitmap = null;
try {
is = getContentResolver().
openInputStream(partURI);
bitmap = BitmapFactory.decodeStream(is);
} catch (IOException e) {}
finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {}
}
}
return bitmap;

}

//Storing image on SD Card
private void storeMmsImageOnSDcard(Bitmap bitmap) {
try {

substr = "A " +k +".PNG";
String extStorageDirectory = Environment.
getExternalStorageDirectory().toString();
File file = new File(extStorageDirectory, substr);
OutputStream outStream = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.PNG,
100,outStream);
outStream.flush();
outStream.close();

Toast.makeText(getApplicationContext(), "Image Saved",
Toast.LENGTH_LONG).show();
Log.v("Debug", "Image seved sucessfully");
}
catch (FileNotFoundException e) {

e.printStackTrace();
Toast.makeText(getApplicationContext(),
e.toString(),
Toast.LENGTH_LONG).show();
} catch (IOException e) {

e.printStackTrace();
Toast.makeText(getApplicationContext(),
e.toString(),
Toast.LENGTH_LONG).show();
}
k++;
}



/* .......methods to get details about Sent MMS.... */
private void getSentMMSinfo() {


Uri uri = Uri.parse("content://mms/sent");
String str = "";
Cursor cursor = getContentResolver().query(uri,
null,null,
null, null);
cursor.moveToNext();

String mms_id= cursor.getString(cursor.
getColumnIndex("_id"));
String phone = cursor.getString(cursor.
getColumnIndex("address"));
String dateVal = cursor.getString(cursor.
getColumnIndex("date"));
Date date = new Date(Long.valueOf(dateVal));
// 2 = sent, etc.
int mtype = cursor.getInt(cursor.
getColumnIndex("type"));
String body="";

Bitmap bitmap;

String type = cursor.getString(cursor.
getColumnIndex("ct"));
if ("text/plain".equals(type)){
String data = cursor.getString(cursor.
getColumnIndex("body"));
if(data != null){
body = getSentMmsText(mms_id);
}
else {
body = cursor.getString(cursor.
getColumnIndex("text"));
//body text is stored here
}
}
else if("image/jpeg".equals(type) ||
"image/bmp".equals(type) ||
"image/gif".equals(type) ||
"image/jpg".equals(type) ||
"image/png".equals(type)){
bitmap = getSentMmsImage(mms_id);
//image is stored here
//now we are storing on SDcard
storeMmsImageOnSDcard(bitmap);
}

str = "Sent MMS: \n phone is: " + phone;
str +="\n MMS type is: "+mtype;
str +="\n MMS time stamp is:"+date;
str +="\n MMS body is: "+body;
str +="\n id is : "+mms_id;


Log.v("Debug","sent MMS phone is: "+phone);
Log.v("Debug","MMS type is: "+mtype);
Log.v("Debug","MMS time stamp is:"+date);
Log.v("Debug","MMS body is: "+body);
Log.v("Debug","MMS id is: "+mms_id);

Toast.makeText(getBaseContext(), str,
Toast.LENGTH_SHORT).show();
Log.v("Debug", "RDC : So we got all informaion " +
"about Sent MMS Message :) ");

}


//method to get Text body from Sent MMS............
private String getSentMmsText(String id) {

Uri partURI = Uri.parse("content://mms/sent" + id);
InputStream is = null;
StringBuilder sb = new StringBuilder();
try {
is = getContentResolver().openInputStream(partURI);
if (is != null) {
InputStreamReader isr = new InputStreamReader(is,
"UTF-8");
BufferedReader reader = new BufferedReader(isr);
String temp = reader.readLine();
while (temp != null) {
sb.append(temp);
temp = reader.readLine();
}
}
} catch (IOException e) {}
finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {}
}
}
return sb.toString();

}

//method to get image from sent MMS............
private Bitmap getSentMmsImage(String id) {

Uri partURI = Uri.parse("content://mms/sent" + id);
InputStream is = null;
Bitmap bitmap = null;
try {
is = getContentResolver().
openInputStream(partURI);
bitmap = BitmapFactory.decodeStream(is);
} catch (IOException e) {}
finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {}
}
}
return bitmap;

}

}//smsObserver class closed
}


dont forget to write entries for permissions and service

AndroidManifest.xml
  































This code is tested on Emulator for SMS and output will be like this..
For Receiving Text SMS:

For Sending Text SMS:

Thanks!!

any suggestions will be appreciated :)

Labels: , , , , , , , ,

Saturday, October 8, 2011

Listening incoming sms message in Android

The following code shows "how to get notification when android mobile receive a message"

We will use only Broadcast Receiver's method not any URI query or something else.


So let's create a simple android app, then delete default Activity and create new java class
which extends Broadcast-receiver  look like this

SMSNotification.java
  
package com.rdc;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.util.Log;
import android.widget.Toast;


public class SMSNotification extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {

Toast.makeText(context,"Wow! we got a Message :)",Toast.LENGTH_SHORT).show();

Bundle bundle = intent.getExtras();
SmsMessage[] msgs = null;
String str = "";
if(bundle != null){
Object[] pdus = (Object[]) bundle.get("pdus");
msgs = new SmsMessage[pdus.length];
for(int i=0; i<msgs.length;i++){
msgs[i]= SmsMessage.createFromPdu((byte[])pdus[i]);
str += "SMS from: " +msgs[i].getOriginatingAddress();
str +="\n"+"Message is:";
str += msgs[i].getMessageBody().toString();
str +="\n";
}

Log.v("Debug", str);
Toast.makeText(context, str, Toast.LENGTH_SHORT).show();
}
}
}


AndroidManifest.xml
  
























output is like this

cheers!!

I'd love to hear your thoughts!

Labels: , ,

Wednesday, October 5, 2011

How to call Activity's Method from Service/Adapter or any java class

Some time we need to call the Activity's method from outside the Activity like any Service/Adapter or any java class. So for that i have created this very simple example.

we need to do two steps.
  1. get the instance of Activity in Service.
  2. call Activity class method from Service
so lets try this small app..

-------------------------------------------
App Name: CallActivityMthodFromService
Package Name: com.rdc
Android SDK: Android SDK 2.3.3 / API 10
Default Activity Name: MyActivity
-------------------------------------------

 MyActivity.java
package com.rdc;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Toast;

public class MyActivity extends Activity {

static MyActivity instance;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
instance = this;
Intent myIntent = new Intent(getBaseContext(), MyService.class);
startService(myIntent);
}

public void showToast() {
Toast.makeText(getBaseContext(), "called from ervice", 1).show();

}
}

MyService.java
package com.rdc;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;

public class MyService extends Service {

@Override
public IBinder onBind(Intent i) {
// TODO Auto-generated method stub
return null;
}

@Override
public void onCreate() {
Log.v("Debug", "Service has been Created..");
// code to execute when the service is first created
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.v("Debug", "Service has been Started..");
Toast.makeText(getBaseContext(), "Service has been Started..",
Toast.LENGTH_SHORT).show();

// getting the static instance of activity
MyActivity activity = MyActivity.instance;

if (activity != null) {
// we are calling here activity's method
activity.showToast();
}

return START_STICKY;
}

}


main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello" />
</LinearLayout>


and Manifest file will be
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.rdc"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="10" />

<application
android:icon="@drawable/icon"
android:label="@string/app_name">
<activity
android:name=".MyActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:enabled="true"
android:name=".MyService" />

</application>
</manifest>


The output Screen will be like this..


You can download the complete source code zip file here : CallActivityMthodFromService 

 cheers!!

 I'd love to hear your thoughts!

Labels: ,