I was wondering if anyone knew anything about programmatically getting the sms messages off of your phone's sim card on an android platform. I would like to write a program that allows you to save either individual messages or entire threads to the sd card, but after looking around for a bit, I have discovered that google decided to take out that api from the current android sdk. I saw in a few places that there are hidden apis for this, but no one knew what they were or how to use them.
Here is a code snippet that lets you read messages.
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.gsm.SmsMessage;
import android.telephony.gsm.SmsManager;
import android.widget.Toast;
public class SMSReceiver extends BroadcastReceiver
{
public void onReceive(Context context, Intent intent)
{
Bundle myBundle = intent.getExtras();
SmsMessage [] messages = null;
String from= "";
String body="";
boolean inSIM=false;
if (myBundle != null)
{
Object [] pdus = (Object[]) myBundle.get("pdus");
messages = new SmsMessage[pdus.length];
for (int i = 0; i < messages.length; i++)
{
messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
from = ""+messages[i].getOriginatingAddress();
body = ""+messages[i].getMessageBody();
inSIM = (messages[i].getIndexOnSim() != -1);
if (inSIM)
{
int status = messages[i].getStatusOnSim();
if (status == SmsManager.STATUS_ON_SIM_UNREAD)
{
Toast.makeText(context, "Message Unread on SIM: "+from+": "+body, Toast.LENGTH_SHORT).show();
}
}
}
}
}
}
Another simple approach is
class SmsReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val messages = Telephony.Sms.Intents.getMessagesFromIntent(intent)
}
}
Related
In most Android devices, the RecognitionService will be supplied by Google's native 'Now/Assistant' application.
Up until Android Oreo, I was able to query the languages supported by the Google Recognizer with the following simple code:
final Intent vrIntent = new Intent(RecognizerIntent.ACTION_GET_LANGUAGE_DETAILS);
// vrIntent.setPackage("com.google.android.googlequicksearchbox");
getContext().sendOrderedBroadcast(vrIntent, null, new BroadcastReceiver() {
#Override
public void onReceive(final Context context, final Intent intent) {
// final Bundle bundle = intent.getExtras();
final Bundle bundle = getResultExtras(true);
if (bundle != null) {
if (bundle.containsKey(RecognizerIntent.EXTRA_SUPPORTED_LANGUAGES)) {
Log.i("TAG", "onReceive: EXTRA_SUPPORTED_LANGUAGES present");
final ArrayList<String> vrStringLocales = bundle.getStringArrayList(
RecognizerIntent.EXTRA_SUPPORTED_LANGUAGES);
Log.i("TAG", "onReceive: EXTRA_SUPPORTED_LANGUAGES size: " + vrStringLocales.size());
} else {
Log.w("TAG", "onReceive: missing EXTRA_SUPPORTED_LANGUAGES");
}
} else {
Log.w("TAG", "onReceive: Bundle null");
}
}, null, 1234, null, null);
However, since 8.0+ the extra RecognizerIntent.EXTRA_SUPPORTED_LANGUAGES is no longer contained in the response.
Before I attempt to file this as a bug, I wanted to firstly see if others could replicate - but also check if there has been an Ordered Broadcast behavioural change in API 26 I've somehow overlooked, which could be the cause of this.
Thanks in advance.
So, I could't replicate, but further to the comments, if you don't set the package name
vrIntent.setPackage("com.google.android.googlequicksearchbox");
then it fails, otherwise all works fine to me.
That's the basic activity I've used to test it.
package it.versionestabile.stackover001;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.speech.RecognizerIntent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import java.util.ArrayList;
import static java.security.AccessController.getContext;
/**
* https://stackoverflow.com/questions/48500077/recognizerintent-action-get-language-details-in-oreo
*/
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Intent vrIntent = new Intent(RecognizerIntent.ACTION_GET_LANGUAGE_DETAILS);
vrIntent.setPackage("com.google.android.googlequicksearchbox");
PackageManager packageManager = getPackageManager();
for (PackageInfo packageInfo: packageManager.getInstalledPackages(0)) {
if (packageInfo.packageName.contains("com.google.android.googlequicksearchbox"))
Log.d("AAA", packageInfo.packageName + ", " + packageInfo.versionName);
}
this.sendOrderedBroadcast(vrIntent, null, new BroadcastReceiver() {
#Override
public void onReceive(final Context context, final Intent intent) {
// final Bundle bundle = intent.getExtras();
final Bundle bundle = getResultExtras(true);
if (bundle != null) {
if (bundle.containsKey(RecognizerIntent.EXTRA_SUPPORTED_LANGUAGES)) {
Log.i("TAG", "onReceive: EXTRA_SUPPORTED_LANGUAGES present");
final ArrayList<String> vrStringLocales = bundle.getStringArrayList(
RecognizerIntent.EXTRA_SUPPORTED_LANGUAGES);
Log.i("TAG", "onReceive: EXTRA_SUPPORTED_LANGUAGES size: " + vrStringLocales.size());
} else {
Log.w("TAG", "onReceive: missing EXTRA_SUPPORTED_LANGUAGES");
}
} else {
Log.w("TAG", "onReceive: Bundle null");
}
}
}, null, 1234, null, null);
}
}
I've tested it both on Android Studio 2.3 and 3.0.1 and on emulator with API 26 and 27.
All works fine with the above code.
But if you comment out this line:
vrIntent.setPackage("com.google.android.googlequicksearchbox");
on Oreo it doesn't work.
And I still suggest to check the presence of Google Now with Package Manager in a way like this:
PackageManager packageManager = getPackageManager();
for (PackageInfo packageInfo: packageManager.getInstalledPackages(0)) {
if (packageInfo.packageName.contains("com.google.android.googlequicksearchbox"))
Log.d("AAA", packageInfo.packageName + ", " + packageInfo.versionName);
// TODO - set a boolean value to discriminate the precence of google now
}
In order to decide if you have the right version of Google Now.
Hope it helps!
I want my app to vibrate the device using my app's custom vibration pattern. I can do this from MainActivity, or any Activity, but I don't know why it isn't working from within a Java class (SmsReceiver.java).
I thought that if I use ...context.getApplicationContext.getSystemService(Context.VIBRATOR_SERVICE); it would get the MainActivity context and thus would be kind of like I was in the MainActivity and it would vibrate. But nope. It doesn't vibrate from the Receiver class.
How do I vibrate the phone from the SmsReceiver.java class?
SmsReceiver.java:
package com.app.name.app;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Vibrator;
import android.telephony.SmsMessage;
import android.util.Log;
import android.widget.Toast;
public class SmsReceiver extends BroadcastReceiver {
private static final String SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(SMS_RECEIVED)) {
Bundle bundle = intent.getExtras();
if (bundle != null) {
// 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();
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();
Log.d("SNDR", sender);
String message = sb.toString();
// prevent any other broadcast receivers from receiving broadcast
abortBroadcast();
if(!message.isEmpty())
{
if(message == "!")
{
Vibrator v = (Vibrator)context.getApplicationContext().getSystemService(Context.VIBRATOR_SERVICE);
v.cancel();
long[] longs = { 0, 75, 15, 100, 15, 100, 15, 75, 15 };
v.vibrate(longs, -1);
}
}
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
}
}
}
}
MainActivity.java, onButtonClick:
switch(id)
{
case R.id.action_search:
Vibrator v = (Vibrator)getSystemService(Context.VIBRATOR_SERVICE);
long[] longs = { 0, 75, 15, 100, 15, 100, 15, 75, 15 };
v.vibrate(longs, -1);
break;
case R.id.action_settings:
break;
}
This related question does not solve this issue.
I don't believe there's any restriction on using the Vibrator service from a BroadcastReceiver. I think your problem has to do with your String comparison. You should be using String#equals() to test for String equality, not ==.
if(message.equals("!"))
i am new with android SMS and I am trying to study it. So i am trying to make an android app that always works on the background, and when I receive sms with the content of "hello"(somebody sending "hello" to my phone by SMS) a music will play.
I searched all over the internet, and I built a project that worked on the AVD, but when I tested it on my phone it didn't work:
import info.kfsoft.android.R.raw;
import android.app.Notification;
import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.widget.TextView;
import android.widget.Toast;
public class SMSReceiver extends BroadcastReceiver
{
MediaPlayer ourSong;
//static final int uniqueID=12345;
TextView display;
public void onReceive(Context context, Intent intent)
{
NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
ourSong = MediaPlayer.create(context, R.raw.music2);
Bundle myBundle = intent.getExtras();
SmsMessage [] messages = null;
String strMessage = "";
if (myBundle != null)
{
Object [] pdus = (Object[]) myBundle.get("pdus");
messages = new SmsMessage[pdus.length];
for (int i = 0; i < messages.length; i++)
{
messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
// strMessage += "SMS From the king him self: " + messages[i].getOriginatingAddress();
// strMessage += " : ";
strMessage += messages[i].getMessageBody();
// strMessage += "\n";
}
//max volume
AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
am.setStreamVolume(AudioManager.STREAM_MUSIC,am.getStreamMaxVolume(AudioManager.STREAM_MUSIC),0);
Toast.makeText(context, strMessage, Toast.LENGTH_SHORT).show();
// Notification n=new Notification(android.R.drawable.)
// nm.notify(uniqueID,n);
ourSong.start();
}
}
public void a(){
}
}
THX.
Maybe it's your intent priority too low and system-installed SMSApp receives a message before your application. Try adding priority="999"
<receiver android:name="OnAlarmReceiver">
<intent-filter android:priority="999">
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
Another trick is not register SMS_RECEIVED in a AndroidManifest.xml file but programmatically in an application code. Here is an example where I actually register multiple events to a same broadcastreceiver.
broadcastReceiver = new EventReceiver();
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction("android.provider.Telephony.SMS_RECEIVED");
filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY-1);
registerReceiver(broadcastReceiver, filter);
i want to build a android application that first received a message from any number and after
receive message i want hold the message string and number in the variables and then reply message adding some extra string in message to same no automatically without user interface.
i am new in android so please help me.
only i have receiving message code....plese give me solution for rest of code.
thank you
My brodcost reciver class
package com.example.broadcastreceiver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsManager;
import android.telephony.SmsMessage;
import android.util.Log;
import android.widget.Toast;
public class IncomingSms extends BroadcastReceiver {
// Get the object of SmsManager
final SmsManager sms = SmsManager.getDefault();
public void onReceive(Context context, Intent intent) {
// Retrieves a map of extended data from the intent.
final Bundle bundle = intent.getExtras();
try {
if (bundle != null) {
final Object[] pdusObj = (Object[]) bundle.get("pdus");
for (int i = 0; i < pdusObj.length; i++) {
SmsMessage currentMessage = SmsMessage.createFromPdu((byte[]) pdusObj[i]);
String phoneNumber = currentMessage.getDisplayOriginatingAddress();
String senderNum = phoneNumber;
String message = currentMessage.getDisplayMessageBody();
System.out.println(phoneNumber);
System.out.println(currentMessage);
Log.i("SmsReceiver", "senderNum: "+ senderNum + "; message: " + message);
int duration = Toast.LENGTH_LONG;
Toast toast = Toast.makeText(context, "senderNum: "+ senderNum + ", message: " + message, duration);
toast.show();
} // end for loop
} // bundle is null
} catch (Exception e) {
Log.e("SmsReceiver", "Exception smsReceiver" +e);
}
}
}
my main activity
package com.example.broadcastreceiver;
import com.androidexample.broadcastreceiver.R;
import android.os.Bundle;
import android.app.Activity;
public class BroadcastNewSms extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.androidexample_broadcast_newsms);
Ssystem.out.println("")
}
}
Well, you now should send your message from your broadcast, you should:
PendingIntent sentIntent; // can be null
PendingIntent deliveryIntent; // can be null
SmsManager sms = SmsManager.getDefault();
sms.sendTextMessage(phoneNumber, null, message, sentIntent, deliveryIntent);
http://developer.android.com/reference/android/telephony/SmsManager.html
you might consider putting it into IntentService, I am not sure how long execution of sendTextMessage takes, and broadcasts should not do any heavy computations/processing. Also putting this code into IntentService, will prevent android from killing your app, this is important because you want this to work in background and android might create your app just to make it receive broadcast, and after onReceive ends it might kill your app, Service will prolong your app life.
I am developing an android application that would let people send and receive SMS to a unique number via my application. I can send SMS but it is appearing in INBOX message box!
I want it to appear in my application
I googled and find this but I do not want it to appear in Toast message, I want it like in What's app in android and how to save all the SMS from this number?
this is the code:
package net.learn2develop.SMSMessaging;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.gsm.SmsMessage;
import android.widget.Toast;
public class SmsReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
//---get the SMS message passed in---
Bundle bundle = intent.getExtras();
SmsMessage[] msgs = null;
String str = "";
if (bundle != null)
{
//---retrieve the SMS message received---
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 += " :";
str += msgs[i].getMessageBody().toString();
str += "\n";
}
//---display the new SMS message---
Toast.makeText(context, str, Toast.LENGTH_SHORT).show();
}
}
}
As per: Can we delete an SMS in Android before it reaches the inbox?
Incoming SMS message broadcasts
(android.provider.Telephony.SMS_RECEIVED) are delivered as an
"ordered broadcast" — meaning that you can tell the system which
components should receive the broadcast first.
If you define an android:priority attribute on your SMS-listening
, you will then receive the notification before the
native SMS application.
At this point, you can cancel the broadcast, preventing it from
being propagated to other apps.
In your manifest, you should have something that looks like this:
<receiver android:name=".SmsReceiver">
<intent-filter android:priority="999">
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
Note android:priority="999".
In your onReceive() method, the first line should be abortBroadcast();. Timing does matter and you will get bundle from the intent.