Hi. I’m a beginner in android development. I want to create a voice and gesture based messaging app. Now, I’ve created an app which is able to receive and send messages. But i want my app to read incoming messages aloud. Any help in this matter would be appreciated. !.. if you want i can send the whole program to you via email or any other source. Any suggestions to change the ugly layout are also welcome.
Screenshot_20200213-121227|281x500
Below is the whole code.
//Broadcast receiver
package com.example.myapplication;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.widget.Toast;
import androidx.annotation.RequiresApi;
public class SmsBroadcastReceiver extends BroadcastReceiver {
public static final String SMS_BUNDLE = "pdus";
@RequiresApi(api = Build.VERSION_CODES.M)
public void onReceive(Context context, Intent intent) {
Bundle intentExtras = intent.getExtras();
Toast.makeText(context, "Message Received!", Toast.LENGTH_SHORT).show();
if (intentExtras != null) {
Object[] sms = (Object[]) intentExtras.get(SMS_BUNDLE);
String smsMessageStr = "";
for (int i = 0; i < sms.length; ++i) {
String format = intentExtras.getString("format");
SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) sms[i], format);
String smsBody = smsMessage.getMessageBody().toString();
String address = smsMessage.getOriginatingAddress();
smsMessageStr += "SMS From: " + address + "\n";
smsMessageStr += smsBody + "\n";
}
if (MainActivity.active) {
MainActivity inst = MainActivity.instance();
inst.updateInbox(smsMessageStr);
} else {
Intent i = new Intent(context, MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
}
}
}
//Main Activity
package com.example.myapplication;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.content.ContentResolver;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.telephony.SmsManager;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.Toast;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
FloatingActionButton fabNewMsg;
ImageButton newmessage;
public static MainActivity instance() {
return instance();
}
static boolean active = false;
@Override
public void onStart() {
super.onStart();
MainActivity instance = this;
}
@Override
public void onStop() {
super.onStop();
active = false;
}
ArrayList<String> smsMessagesList = new ArrayList<>();
ListView messages;
ArrayAdapter arrayAdapter;
private static final int READ_SMS_PERMISSIONS_REQUEST = 1;
@RequiresApi(api = Build.VERSION_CODES.M)
public void getPermissionToReadSMS() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_SMS)
!= PackageManager.PERMISSION_GRANTED) {
if (shouldShowRequestPermissionRationale(
Manifest.permission.READ_SMS)) {
Toast.makeText(this, "Please allow permission!", Toast.LENGTH_SHORT).show();
}
requestPermissions(new String[]{Manifest.permission.READ_SMS},
READ_SMS_PERMISSIONS_REQUEST);
}
}
@Override
public void onRequestPermissionsResult(int requestCode,
@NonNull String permissions[],
@NonNull int[] grantResults) {
// Make sure it's our original READ_CONTACTS request
if (requestCode == READ_SMS_PERMISSIONS_REQUEST) {
if (grantResults.length == 1 &&
grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "Read SMS permission granted", Toast.LENGTH_SHORT).show();
refreshSmsInbox();
} else {
Toast.makeText(this, "Read SMS permission denied", Toast.LENGTH_SHORT).show();
}
} else {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
public void refreshSmsInbox() {
ContentResolver contentResolver = getContentResolver();
Cursor smsInboxCursor = contentResolver.query(Uri.parse("content://sms/inbox"), null, null, null, null);
int indexBody = smsInboxCursor.getColumnIndex("body");
int indexAddress = smsInboxCursor.getColumnIndex("address");
if (indexBody < 0 || !smsInboxCursor.moveToFirst()) return;
arrayAdapter.clear();
do {
String str = "SMS From: " + smsInboxCursor.getString(indexAddress) +
"\n" + smsInboxCursor.getString(indexBody) + "\n";
arrayAdapter.add(str);
} while (smsInboxCursor.moveToNext());
}
@RequiresApi(api = Build.VERSION_CODES.M)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
messages = (ListView) findViewById(R.id.messages);
// EditText input = (EditText) findViewById(R.id.input);
arrayAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, smsMessagesList);
messages.setAdapter(arrayAdapter);
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_SMS)
!= PackageManager.PERMISSION_GRANTED) {
getPermissionToReadSMS();
} else {
refreshSmsInbox();
}
fabNewMsg = findViewById(R.id.fab_new);
fabNewMsg.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Intent code for open new activity through intent.
Intent intent = new Intent(MainActivity.this, SmsSend.class);
startActivity(intent);
}
});
newmessage = (ImageButton)findViewById(R.id.sttact);
newmessage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Intent code for open new activity through intent.
Intent intent = new Intent(MainActivity.this, Speechtotext.class);
startActivity(intent);
}
});
messages.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
smsMessagesList.remove(position);
arrayAdapter.notifyDataSetChanged();
Toast.makeText(MainActivity.this, "Item Deleted", Toast.LENGTH_LONG).show();
return true;
}
});
}
//sending sms
EditText input;
SmsManager smsManager = SmsManager.getDefault();
@RequiresApi(api = Build.VERSION_CODES.M)
public void onSendClick(View view) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.SEND_SMS)
!= PackageManager.PERMISSION_GRANTED) {
getPermissionToReadSMS();
} else {
smsManager.sendTextMessage("+923322977643c", null, input.getText().toString(), null, null);
Toast.makeText(this, "Message sent!", Toast.LENGTH_SHORT).show();
}
}
public void updateInbox(String smsMessageStr) {
}
}
// Sms send speech to text implemented.
package com.example.myapplication;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.speech.RecognizerIntent;
import android.speech.tts.TextToSpeech;
import android.speech.tts.UtteranceProgressListener;
import android.telephony.SmsManager;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import com.google.android.material.textfield.TextInputEditText;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Locale;
public class Speechtotext extends AppCompatActivity {
int Ask_Contact = 11;
int Ask_MESSAGE = 12;
int Send_OR_CANCEL = 13;
int SEND_MSG_OR_CANCEL_MSG;
int CANCEL_MESSAGE = 14;
Context context;
TextToSpeech tts;
public String FULL_MESSAGE, CONTACT_NUMBER = null;
private String number = null;
private String ret = null;
private String username = null;
private String No = null;
private String body = null;
private ListView contactsList;
TextView phone_number;
Button sendBtn;
Button mcancel;
ImageView micBtn;
TextInputEditText mMessage;
Spinner mContact;
HashMap<String,String> map;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_speechtotext);
context=getApplicationContext();
contactsList = findViewById(R.id.contact_list);
sendBtn = (Button) findViewById(R.id.btnsend);
mcancel = (Button) findViewById(R.id.btncancel);
micBtn=(ImageView)findViewById(R.id.mic_btn);
mContact = (Spinner) findViewById(R.id.textInputEditText);
mMessage = (TextInputEditText) findViewById(R.id.textInputEditText2);
phone_number=(TextView)findViewById(R.id.tv_phone);
map = new HashMap<String, String>();
tts = new TextToSpeech(getApplicationContext(), new TextToSpeech.OnInitListener() {
@Override
public void onInit(int status) {
map.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,"UniqueID");
if (status != TextToSpeech.ERROR) {
tts.setLanguage(new Locale("ur"));
tts.speak("Who do you want to send the message", TextToSpeech.QUEUE_FLUSH, map);
tts.setOnUtteranceProgressListener(new UtteranceProgressListener() {
@Override
public void onStart(String utteranceId) {
}
@Override
public void onDone(String utteranceId) {
startVoiceRecognization(Ask_Contact);
}
@Override
public void onError(String utteranceId) {
}
});
} }});
micBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v)
{
resetActivity();
}
});
mcancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
resetActivity();
}
});
sendBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (CONTACT_NUMBER != null && FULL_MESSAGE != null) {
sendSms(CONTACT_NUMBER, FULL_MESSAGE);
}
}
});
}
public void resetActivity()
{
Intent intent = getIntent();
overridePendingTransition(0, 0);
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
finish();
overridePendingTransition(0, 0);
startActivity(intent);
}
//to speak or system response
public void speakAndStartListening(final String text, final int RequestCode)
{
tts.speak(text, TextToSpeech.QUEUE_FLUSH, map);
tts.setOnUtteranceProgressListener(new UtteranceProgressListener()
{
@Override
public void onStart(String s)
{ }
@Override
public void onDone(String s)
{
startVoiceRecognization(RequestCode);
}
@Override
public void onError(String s)
{ }
});
}
public void speakOnly(final String text)
{
tts.speak(text, TextToSpeech.QUEUE_FLUSH, map);
}
//tostart listeining
public void startVoiceRecognization(int CODE)
{
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
startActivityForResult(intent, CODE);
}
//results of voice recognization
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
//result of contact
if (requestCode == Ask_Contact && resultCode == RESULT_OK)
{
ArrayList matches = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
number = matches.get(0).toString();
Cursor contacts = getListOfContactNames(number);
String from[]={ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER};
int ids[]={R.id.tv_name,R.id.tv_phone};
SimpleCursorAdapter simpleCursorAdapter=new SimpleCursorAdapter(getApplicationContext(),
R.layout.contact_list_view_item,contacts,from,ids,0);
mContact.setAdapter(simpleCursorAdapter);
//OR USING CUSTOMADAPTER
//ContactAdapter contactAdapter=new ContactAdapter(getApplicationContext(),contacts);
// mContact.setAdapter(contactAdapter);
if (mContact.getCount()==0)
{
speakAndStartListening("Sorry! say the name again",Ask_Contact);
}
else if (mContact.getCount() > 1)
{
mContact.performClick();
speakOnly("which one?" + number);
//START SOME WORK AFTER SPEECH IS ENDED
tts.setOnUtteranceProgressListener(new UtteranceProgressListener()
{
@Override
public void onStart(String s) { }
@Override
public void onDone(String s)
{
mContact.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener()
{@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l)
{
Cursor cursor=(Cursor)adapterView.getItemAtPosition(i);
CONTACT_NUMBER= cursor.getString(2);
speakAndStartListening("Please speak your message.",Ask_MESSAGE);
}
@Override
public void onNothingSelected(AdapterView<?> adapterView)
{ }
});
return;
}
@Override
public void onError(String s)
{
speakOnly(s);
startVoiceRecognization(Ask_Contact);
}
});
}
else
{
speakAndStartListening("Please speak your message",Ask_MESSAGE);
}
}
//result of change contact or send
if (requestCode == Send_OR_CANCEL && resultCode == RESULT_OK)
{
ArrayList matches = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
if (matches.get(0).equals("change")||matches.get(0).equals("change it"))
{
startVoiceRecognization(Ask_Contact);
}
else if (matches.get(0).equals("send")||matches.get(0).equals("send it"))
{
speakAndStartListening("What is your message",Ask_MESSAGE);
}
}
//result of user message
if (requestCode == Ask_MESSAGE && resultCode == RESULT_OK)
{
ArrayList matches = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
FULL_MESSAGE = matches.get(0).toString();
mMessage.setText(FULL_MESSAGE);
speakAndStartListening("send message or change it",SEND_MSG_OR_CANCEL_MSG);
}
//result of change message or send
if (requestCode == SEND_MSG_OR_CANCEL_MSG && resultCode == RESULT_OK)
{
ArrayList matches = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
if (matches.get(0).equals("change")||matches.get(0).equals("change it")||
matches.get(0).equals("change kar do")||matches.get(0).equals("Badal do")
||matches.get(0).equals("Badal"))
{
speakAndStartListening("speak your message",Ask_MESSAGE);
}
else if (matches.get(0).equals("send")||matches.get(0).equals("send it")
||matches.get(0).equals("send kar do"))
{
sendSms(CONTACT_NUMBER, FULL_MESSAGE);
// speakOnly(".");
}
else
{
speakAndStartListening("please speak again" +
"",SEND_MSG_OR_CANCEL_MSG);
}
}
}
public void sendSms(String no, String body)
{
SmsManager smgr = SmsManager.getDefault();
smgr.sendTextMessage(no, null, body, null, null);
toast("SMS Sent Successfully");
}
public Cursor getListOfContactNames(String searchText)
{
Cursor cur = null;
ContentResolver cr = getContentResolver();
String[] mProjection = new String[]{ContactsContract.CommonDataKinds.Phone._ID,
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.NUMBER,
ContactsContract.CommonDataKinds.Phone.NORMALIZED_NUMBER};
Uri uri = ContactsContract.Contacts.CONTENT_URI;
String selection = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " like'%" + searchText + "%'";
cur = context.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
mProjection, selection, null, null);
return cur;
}
public void toast(String text)
{
Toast.makeText(getApplicationContext(),text,Toast.LENGTH_SHORT).show();
}
}
// Android manifest file.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myapplication">
<uses-permission android:name="android.permission.WRITE_SMS" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:allowBackup="true"
android:icon="@drawable/mic"
android:label="@string/app_name"
android:roundIcon="@drawable/mic"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<action android:name="android.intent.action.SEND" />
<action android:name="android.intent.action.SENDTO" />
</intent-filter>
</activity>
<activity android:name=".Speechtotext" />
<activity android:name=".SmsSend"/>
<receiver
android:name=".SmsBroadcastReceiver"
android:exported="true"
android:permission="android.permission.BROADCAST_SMS">
<intent-filter android:priority="999">
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
<action android:name="android.provider.Telephony.SMS_DELIVER" />
<action android:name="android.provider.Telephony.SMS_DELIVER_ACTION" />
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
</manifest>