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 :)

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!

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!