0

I am creating an app where the user fills a form and sends an SMS to a phone number. The app then logs the data to a csv file. The app should record data when SMS is sent but exactly opposite is happening. The data is recorded when SMS is not sent and data is not recorded when SMS is sent, could anyone kidly help? Here is my code and XML file.

Code:

    package com.mycompany.sms1;

import android.app.*;
import android.content.*;
import android.os.*;
import android.telephony.*;
import android.telephony.gsm.*;
import android.view.*;
import android.widget.*;
import java.io.*;

import android.telephony.gsm.SmsManager;


public class MainActivity extends Activity 
{

    EditText name, labnum, txtPhoneNo, amount;
    Button btnSendSMS;
    static boolean success=false;

    String imei=/*"351892081280633";//*/"865735030867621";
    String phoneNo,message,data;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        TelephonyManager tm=(TelephonyManager)getSystemService(this.TELEPHONY_SERVICE);

        if (imei.equals(tm.getDeviceId())) setContentView(R.layout.main);
        else {setContentView(R.layout.register); return;}

        name = (EditText) findViewById(R.id.name);
        labnum = (EditText) findViewById(R.id.labnum);
        txtPhoneNo = (EditText) findViewById(R.id.txtPhoneNo);
        amount = (EditText) findViewById(R.id.amount);
        btnSendSMS = (Button) findViewById(R.id.btnSendSMS);

    }

    public void buttonClicked(View v) 
    { 

        if (EverythingIsOK())
        {
            phoneNo = txtPhoneNo.getText().toString();
            message = "Thanks for the payment.";
            sendSMS(phoneNo, message);
            try{Thread.sleep(1000);}catch(Exception e){}
            if(success) storeData();    
            success=false;
        }
    }

    public void clearClicked(View v) 
    { 
        name.setText("");
        labnum.setText("");
        txtPhoneNo.setText("");
        amount.setText("");

    }


    private boolean EverythingIsOK()
    {
        if(checkExternalMedia() && checkData()) return true;
        return false;
    }

    /** Method to check whether external media available and writable. This is adapted from
     http://developer.android.com/guide/topics/data/data-storage.html#filesExternal */

    private boolean checkExternalMedia()
    {
        boolean mExternalStorageAvailable = false;
        boolean mExternalStorageWriteable = false;

        String state = Environment.getExternalStorageState();

        if (Environment.MEDIA_MOUNTED.equals(state))
        {
            // Can read and write the media
            mExternalStorageAvailable = mExternalStorageWriteable = true;
            return true;
        }
        else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state))
        {
            // Can only read the media
            mExternalStorageAvailable = true;
            mExternalStorageWriteable = false;
            showToast("SD Card is not writable.");
        }
        else
        {
            // Can't read or write
            mExternalStorageAvailable = mExternalStorageWriteable = false;
            showToast("SD Card is neither readable nor writable.");
        }   
        return false;
    }


    //---sends an SMS message to another device---
    private void sendSMS(String phoneNumber, String message)
    {
        String SENT = "SMS_SENT";
        String DELIVERED = "SMS_DELIVERED";

        PendingIntent sentPI = PendingIntent.getBroadcast(this, 0,
                                                          new Intent(SENT), 0);

        PendingIntent deliveredPI = PendingIntent.getBroadcast(this, 0,
                                                               new Intent(DELIVERED), 0);

        //---when the SMS has been sent---
        registerReceiver(new BroadcastReceiver(){
                @Override
                public void onReceive(Context arg0, Intent arg1)
                {
                    switch (getResultCode())
                    {
                        case Activity.RESULT_OK: showToast("SMS sent."); setSuccess(true);break;
                        case SmsManager.RESULT_ERROR_GENERIC_FAILURE: showToast("Generic failure."); break;
                        case SmsManager.RESULT_ERROR_NO_SERVICE:showToast("No service."); break;
                        case SmsManager.RESULT_ERROR_NULL_PDU:showToast("Null PDU."); break;
                        case SmsManager.RESULT_ERROR_RADIO_OFF: showToast("Radio off."); break;
                    }
                }
            }, new IntentFilter(SENT));
        /*
         //---when the SMS has been delivered---
         registerReceiver(new BroadcastReceiver(){
         @Override
         public void onReceive(Context arg0, Intent arg1)
         {
         switch (getResultCode())
         {
         case Activity.RESULT_OK: showToast("SMS delivered."); break;
         case Activity.RESULT_CANCELED: showToast("SMS not delivered."); break;
         }
         }
         }, new IntentFilter(DELIVERED));        

         */
        try{
            SmsManager sms = SmsManager.getDefault();
            sms.sendTextMessage(phoneNumber, null, message, sentPI, deliveredPI);  
        }catch (Exception e){showToast(e.toString());}

    }


    private void setSuccess(boolean b){
        success=b;
    }







    /** Method to write ascii text characters to file on SD card. Note that you must add a 
     WRITE_EXTERNAL_STORAGE permission to the manifest file or this method will throw
     a FileNotFound Exception because you won't have write permission. */


    private boolean checkData()
    {
        String s1=name.getText().toString();
        String s2=labnum.getText().toString();
        String s3=txtPhoneNo.getText().toString();
        String s4=amount.getText().toString();

        if (s1.contains(",") || s2.contains(",") || s3.contains(",") || s4.contains(","))
        {       
            showToast("Comma is not allowed.");
            return false;
        }

        if (s1.isEmpty() || s2.isEmpty() || s3.isEmpty() || s4.isEmpty())
        {

            showToast("Please fill all the details.");
            return false;
        }

        data=s1 + "," + s2 + "," + s3 + "," + s4 + "," + "\n";
        return true;
    }


    private boolean storeData()
    {
        writeToSDFile();
        return true;
    }


    private boolean writeToSDFile()
    {

        File root,dir,file;
        // Find the root of the external storage.
        // See http://developer.android.com/guide/topics/data/data-  storage.html#filesExternal

        root = android.os.Environment.getExternalStorageDirectory(); 
        //labnum.setText("\nExternal file system root: "+root);

        // See http://stackoverflow.com/questions/3551821/android-write-to-sd-card-folder

        dir = new File(root.getAbsolutePath());
        dir.mkdirs();
        file = new File(dir, "data.csv");

        try
        {
            FileOutputStream f = new FileOutputStream(file, true);
            PrintWriter pw = new PrintWriter(f);
            pw.print(data);
            pw.flush();
            pw.close();
            f.close();
            showToast("Data saved to " + file);
            return true;
        }
        catch (FileNotFoundException e)
        {
            e.printStackTrace();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }   
        return false;
    }






    private void showToast(String toastText)
    {
        Context context=getApplicationContext();
        int duration= Toast.LENGTH_SHORT;
        Toast toast=Toast.makeText(context, toastText, duration);
        toast.setGravity(Gravity.CENTER, 0, 0);
        toast.show();
    }
}

XML File:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_height="match_parent"
    android:layout_width="match_parent"
    android:orientation="vertical"
    android:background="#CDDC39">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:text="@string/doctor"
        android:layout_marginTop="20dp"
        android:layout_marginLeft="10dp"/>

    <LinearLayout
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:orientation="vertical"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:layout_marginTop="25dp"
        android:layout_marginBottom="40dp">

        <LinearLayout
            android:layout_height="wrap_content"
            android:layout_width="match_parent"
            android:orientation="horizontal"
            android:gravity="right|center_vertical"
            android:layout_marginBottom="10dp">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textAppearance="?android:attr/textAppearanceMedium"
                android:text="@string/name"
                android:textColor="#000000"
                android:textStyle="bold"/>

            <EditText
                android:layout_height="wrap_content"
                android:layout_width="0dp"
                android:ems="10"
                android:layout_weight="1"
                android:layout_marginLeft="10dp"
                android:textColor="#000000"
                android:id="@+id/name"/>

        </LinearLayout>

        <LinearLayout
            android:layout_height="wrap_content"
            android:layout_width="match_parent"
            android:orientation="horizontal"
            android:gravity="center_vertical"
            android:layout_marginBottom="10dp">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textAppearance="?android:attr/textAppearanceMedium"
                android:text="@string/labnum"
                android:textColor="#000000"
                android:textStyle="bold"/>

            <EditText
                android:layout_height="wrap_content"
                android:layout_width="0dp"
                android:ems="10"
                android:layout_weight="1"
                android:layout_marginLeft="10dp"
                android:textColor="#000000"
                android:id="@+id/labnum"/>

        </LinearLayout>

        <LinearLayout
            android:layout_height="wrap_content"
            android:layout_width="match_parent"
            android:orientation="horizontal"
            android:gravity="center_vertical"
            android:layout_marginBottom="10dp">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textAppearance="?android:attr/textAppearanceMedium"
                android:text="@string/phone"
                android:textColor="#000000"
                android:textStyle="bold"/>

            <EditText
                android:layout_height="wrap_content"
                android:layout_width="0dp"
                android:ems="10"
                android:layout_weight="1"
                android:layout_marginLeft="10dp"
                android:textColor="#000000"
                android:inputType="phone"
                android:id="@+id/txtPhoneNo"/>

        </LinearLayout>

        <LinearLayout
            android:layout_height="wrap_content"
            android:layout_width="match_parent"
            android:orientation="horizontal"
            android:gravity="center_vertical">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textAppearance="?android:attr/textAppearanceMedium"
                android:text="@string/amount"
                android:textColor="#000000"
                android:textStyle="bold"/>

            <EditText
                android:layout_height="wrap_content"
                android:layout_width="0dp"
                android:ems="10"
                android:layout_weight="1"
                android:layout_marginLeft="10dp"
                android:textColor="#000000"
                android:inputType="numberDecimal"
                android:id="@+id/amount"/>

        </LinearLayout>

    </LinearLayout>

    <LinearLayout
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:orientation="horizontal"
        android:gravity="center">

        <Button
            android:layout_height="wrap_content"
            android:layout_width="wrap_content"
            android:text="@string/send"
            android:textColor="#FFFFFF"
            android:background="#404040"
            android:id="@+id/btnSendSMS"
            android:onClick="buttonClicked"
            android:layout_marginRight="5dp"/>

        <Button
            android:layout_height="wrap_content"
            android:layout_width="wrap_content"
            android:text="@string/clear"
            android:background="#FFFFFF"
            android:textColor="#404040"
            android:onClick="clearClicked"
            android:layout_marginLeft="5dp"/>

    </LinearLayout>

    <LinearLayout
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:orientation="horizontal"/>

</LinearLayout>
Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62

1 Answers1

0

Sending SMS and getting result via Broadcast is Asynchronous operation. After calling sendSMS(phoneNo, message) method you are sleeping Thread for 1 second. There is no guaranty that you will get result back within 1 second. Suppose you send a sms and it took 1.5 second to get result back, for that case you are writing data before you got response as you are waiting 1 second and writing data.

Write data after you got response. Write data inside onReceive method after switch statement.

Don't sleep MainThread. It will create a bad user experience. Avoid this practice. If you need to wait for something done the use BackgroudnThread and use sleep on that Thread.

Abu Yousuf
  • 5,729
  • 3
  • 31
  • 50
  • That Thread.sleep line was not there earlier. I added it because the 'data saved' toast was appearing before the 'SMS sent' toast. I was just exploring if sleep method could help display the 'SMS sent' toast before the 'data saved' toast. I want to send the sms and save the data after the sms is sent and not the other way. – Mohan Pathak Apr 02 '18 at 09:29
  • Also, if sms is not sent, the data should not be saved. – Mohan Pathak Apr 02 '18 at 09:39
  • Then only write data for successful send case. – Abu Yousuf Apr 02 '18 at 09:41
  • Ya, Thanks. However, now it's writing data multiple times, although sms is sent only once. For example, if it is seventh entry, it is writing the data seven times! – Mohan Pathak Apr 02 '18 at 10:01
  • Then your `case Activity.RESULT_OK` case is executing multiple times. – Abu Yousuf Apr 02 '18 at 10:05
  • first call `checkData()` and then `storeData` inside successful case. – Abu Yousuf Apr 02 '18 at 10:09
  • I cannot do that, because checkData() is required before sending sms. – Mohan Pathak Apr 02 '18 at 10:21