How to read sms using Service - android

I am receiving sms using Broadcast Receiver.It is working fine. Now I want to read sms from inbox using service, (which is received by broadcast receiver).
I want to retreive sms from inbox using SERVICE. SMS retreival must be happen in background not in main thread.No any Activity should be used.
//Broadcast receiver to receive sms and starting a service via intent
public class SMSReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
SmsMessage[] message = null;
String str = "";
if(bundle != null){
Object[] pdus = (Object[])bundle.get("pdus");
message = new SmsMessage[pdus.length];
for(int i = 0; i<message.length; i++){
message[i] = SmsMessage.createFromPdu((byte[])pdus[i]);
str += "New SMS from cloudy contacts " + message[i].getOriginatingAddress();
}
Toast.makeText(context, str, Toast.LENGTH_LONG).show();
Intent intent1 = new Intent(context,MyService.class);
context.startService(intent1);
}
}
}
Servie
public class MyService extends Service{
ReadSMS readSMS;
#Override
public IBinder onBind(Intent arg0) {
return null;
}
public void onCreate(Bundle savedInstanceState){
Log.d("Service","inside onCreate of service");
}
public void onDestroy(){
Log.d("Service", "destroyed");
}
public void onStart(){
Log.d("Service","starting service to read sms from inbox");
Toast.makeText(this,"Reading sms from inbox",Toast.LENGTH_LONG).show();
readSMS = new ReadSMS();
ArrayList list = readSMS.readSms("inbox");
}
public class ReadSMS{
public ArrayList readSms(String inbox){
ArrayList sms = new ArrayList();
Uri uri = Uri.parse("content://sms/inbox");
Cursor cursor = getContentResolver().query(uri, new String[]{"_id","address","date","body"},null,null,null);
cursor.moveToLast();
String address = cursor.getString(1);
String body = cursor.getString(3);
sms.add(address+" "+body);
return sms;
}
}
}

The Messages in the inbox wouldn't be received by a broadcast receiver since it's not a broadcast. You will have to read the native database on the device.
Take a look here
EDIT:
First of all, doing something from a Service doesn't automatically spawn a background thread. The service will run on the main thread.
Caution: A service runs in the main thread of its hosting process—the service does not create its own thread and does not run in a separate process (unless you specify otherwise). This means that, if your service is going to do any CPU intensive work or blocking operations (such as MP3 playback or networking), you should create a new thread within the service to do that work. By using a separate thread, you will reduce the risk of Application Not Responding (ANR) errors and the application's main thread can remain dedicated to user interaction with your activities.
Then you can of course spawn a thread yourself, or use an IntentService. But start by reading here.

Related

How better send data from BroadcastReceiver to Activity?

I wan catch SMS in my app and show it o my view. I create BroadcastReceiver:
public class SMSMonitor extends BroadcastReceiver {
private static final String ACTION = "android.provider.Telephony.SMS_RECEIVED";
#Override
public void onReceive(Context context, Intent intent) {
if (intent != null && intent.getAction() != null && ACTION.compareToIgnoreCase(intent.getAction()) == 0) {
Object[] pduArray = (Object[]) intent.getExtras().get("pdus");
SmsMessage[] messages = new SmsMessage[pduArray.length];
for (int i = 0; i < pduArray.length; i++) {
messages[i] = SmsMessage.createFromPdu((byte[]) pduArray[i]);
}
StringBuilder bodyText = new StringBuilder();
for (SmsMessage message : messages) {
bodyText.append(message.getMessageBody());
}
String body = bodyText.toString();
Toast.makeText(context, body, Toast.LENGTH_LONG).show();
abortBroadcast();
}
}
}
And it show Toast wuth SMS body. Now i dont know what should I do
Create Service and pass SMS to service. And get SMS from service
Use Otto observer and send data(SMS) from:
1. BroadcastReceiver
2. Service
and catch in my activity.
Another more correct way
And if I will use Otto (I want it) where better send data - from BroadcastReceiver or pass data to service and send otto message from Service?
Otto or EventBus is for me the most simple solution and the solution that will reflect best your Activity lifecycle.
A great start is to register/unregister your bus from onPause() and onResume like so :
#Override
public void onResume() {
super.onResume();
BusProvider.getInstance().register(this);
}
#Override
public void onPause() {
super.onPause();
BusProvider.getInstance().unregister(this);
}
Next, post an event from your BroadcastReceiver like BusProvider.getInstance().post(new SmsEvent());
Your fragment or Activity will received the event via the #Subscribe method and the SmsEvent parameter type of the method.
It seems you don't need any Service here except if you want to save the data when the activity is not open.

Error in broadcast receiver for android, it listens to all SMSs that my phone receives

I'm doing an encryption SMS app, in which, user can encrypt the text and send SMS through my apps.
I used the following broadcast receiver.
The problem is that its listen to all the SMS that come to my phone.
How to make it so that it will only listen to the SMS sent from my apps? Other sms's should open as normal, using default SMS application
public class SmsBroadCastReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
// Specify the bundle to get object based on SMS protocol "pdus"
Object[] object = (Object[]) bundle.get("pdus");
SmsMessage sms[] = new SmsMessage[object.length];
Intent in=new Intent(context,DisplaySMSActivity.class);
in.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
in.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
String msgContent = "";
String originNum = "";
StringBuffer sb = new StringBuffer();
for (int i = 0; i < object.length; i++) {
sms[i] = SmsMessage.createFromPdu((byte[]) object[i]);
// get the received SMS content
msgContent = sms[i].getDisplayMessageBody();
//get the sender phone number
originNum = sms[i].getDisplayOriginatingAddress();
//aggregate the messages together when long message are fragmented
sb.append(msgContent);
//abort broadcast to cellphone inbox
abortBroadcast();
}
//fill the sender's phone number into Intent
in.putExtra("originNum", originNum);
//fill the entire message body into Intent
in.putExtra("msgContent", new String(sb));
//start the DisplaySMSActivity.java
context.startActivity(in);
}
Maybe you are not correctly registering your receiver.
When declaring a Receiver in the manifest (or programmatically), you can also specify an intent filter. You can specify the 'action' you want to receive in your receiver.
For example: "com.your_app_package.sms_encrypted_msg".
Either way, remember to check the action in the onReceive method:
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals('com.your_app_package.sms_encrypted_msg')){
...
}
}

send data from a broadcast to an activity . how to do send?

how to send data from a broadcatReceiver to an activity in android as saying catch the received SMS and send the SMS (is the data) to the activity its my first time that i work with broadcatReceiver so can anyone help me i will appreciate any help.
i read several tutorials about the data transferring that have some steps :
create a class that extends activity
create a class that extends broadcastReceiver
but i did not know how is the communication between these 2 classes.
I would do something like that:
public class YourActivity extends Activity
{
private Handler handler = null;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.id.main_layout);
this.handler = new Handler() {
#Override
public void handleMessage(Message msg)
{
SmsMessage sms = (SmsMessage) msg.obj;
String senderNumber = sms.getOriginatingAddress();
}
};
// Register a new receiver that will trigger on SMS_RECEIVED event
IntentFiler filer = new IntentFilert("android.provider.Telephony.SMS_RECEIVED");
registerReceiver(mSmsReceiver, filter);
}
#Override
protected void onDestroy()
{
super.onDestroy();
// Unregister the receiver
unregisterReceiver(mSmsReceiver);
}
private mSmsReceiver = new BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent)
{
Bundle bundle = intent.getExtras();
if (bundle == null || bundle.containsKey("pdus") return;
// Decode the message
SmsMessage sms = SmsMessage.createFromPdu((byte[]) pdus[0]);
// Notify the activity with the message
Message msg = new Message;
msg.obj = sms;
YourActivity.this.handler.sendMessage(msg);
}
};
}
The receiver and the Activity are separate entities and do not usually interact directly. Imagine the following scenario: you have a receiver getting lots of SMS messages, and every time you get one, you launch an Activity to show the message received. Wouldn't this be very annoying to the user?
I'd says that you can interact with the user by creating a Notification and if the user clicks on it, then you open the Activity you want to show the details.
As how to pass the data to the Activity (hopefully using a notification first), given that SMS messages are short in nature you can just put the data in the Intent.
How to set a Notification to launch an Activity: see Open application after clicking on Notification

Best way to communicate a service with an activity (broadcast, callbacks, etc)

What I have:
I have a library running on a process using aidl.
I have an app that uses this library, and on the messaging activity, I connect with the service to send messaging and I have a broadcast receiver to manage the incoming messages.
The problem?
if this library are going to be used by two apps on the same device the broadcast actions are going to be the same, and I will have problems when I send a broadcast.
What is my doubt?
What is the best way to "listen" the new incoming messages that I receive on my library and send it to the App.
Maybe a callback? or there are any better solution?
More information
The library provides a few methods to start a session, and other methods for send different type of messages (images, text, locations, etc...) and I receive a callback from another library, that uses C and C++, when a new message is incoming.
If you need more information feel free to ask.
My Code:
IRemote.aidl
interface IRemote
{
int sendTextMessage(String to, String message);
}
WrapperLibrary.java
public class MyLibrary extends Service {
// Current context, used to sendbroadcast() from #Callbacks
private Context mContext = this;
private static MyLibrary instance = new MyLibrary();
//Executor to start a new thread from the service.
final ExecutorService service;
#Override
public IBinder onBind(Intent arg0) {
//Return the interface.
return mBinder;
}
/** Return the current instance */
public static WrapperLibrary getInstance() {
return instance;
}
private final IRemote.Stub mBinder = new IRemote.Stub() {
#Override
public int sendTextMessage(String to, String message)
throws RemoteException {
Log.d(TAG, "Send Text Message. ");
int i = -1;
Future<Integer> task;
task = service.submit(new Callable<Integer>() {
public Integer call() {
return tu.tu_message_send_text(to, message);
}
});
try {
i = task.get();
} catch (Exception e) {
Log.e(TAG, "Send Text Message: EXCEPTION *** " + e.getMessage());
}
Log.d(TAG, "Send Text Message: Status Code: " + i);
return 0;
}
}
Callbacks.java
public class Callbacks extends JNICallback {
private Context mContext;
public Callbacks(Context context) {
this.mContext = context;
}
public void on_incoming_text_message(final String from, final String message) {
Log.d(TAG, " Incoming TEXT message from:" + from + " with message: " + message);
Intent i = new Intent(BroadcastActions.INCOMING_TEXT_MESSAGE);
i.putExtra("from", from);
i.putExtra("message", message);
mContext.sendBroadcast(i);
}
}
MainActivity.java
On this activity I have a broadcast receiver and I can update the UI with a new message
public class MessageReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Bundle extra = intent.getExtras();
String incomingMessage = "";
if(extra != null) {
incomingMessage = extra.getString("message");
addNewMessage(new Message(incomingMessage, false));
}
Toast.makeText(MessagingActivity.this, "Incoming Message", Toast.LENGTH_LONG).show();
}
};
I was going to suggest to use LocalBroadcastManager or if it becomes messy EventBus, but if the service runs in its own process (which is not something I'm sure about) the messaging will not be passed from one process to the other.
So I would suggest to define the Broadcast Action from the service in strings.xml and make it different for every app. Of course, you'll have to be careful as you'll need also to update the receiver action for every app.
Well, finally I will use a Callbacks implementation.
The architecture is going to be like this:
App
Main Activity (Connect with the LibService)
LibService (is going to have the callbacks and broadcast receivers)
Library
Callbacks and interfaces but not running in a service.
This is the best approach to me to the future integration on other projects, and the library is going to be more simple without aidl and services.
I thought the use of the receivers was a very good options, but thinking about the integration on other projects this is the best way to do it (for me).

How to send data to a running activity from Broadcast Receiver,

I am able to receive C2DM message fine but I want to send the data to a running activity, i.e when the activity is running, if the receiver receives C2DM message it is to send the data to the running activity. The code of receiver is (no bugs in the code):
public class C2dmreceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.w("C2DM", "Message Receiver called");
if ("com.google.android.c2dm.intent.RECEIVE".equals(action))
{
final String payload = intent.getStringExtra("key1");
Log.d("C2DM", "message = " + payload );
}
}}
I have tried like this inside the activity in an attempt to register the receiver in the activity so that the receiver can send data and the running activity can receive the data :-
C2dmreceiver c2dmr = new C2dmreceiver();
Registration.this.registerReceiver(c2dmr, new IntentFilter());
I don't know what to put inside the IntentFilter(), also what else I have to put in the code of the activity and the code of the receiver so that while the activity is running and some C2DM message comes the receiver can send the data to the running activity.
So, please tell me the code that is to put in the activity and in the receiver and may also be in the manifest so that the data from the receiver could be send to running activity.
Any advice is highly appreciated.
First of all it's not the best idea to subscribe c2dm receiver in activity. Do it in manifest. For passing data to activity you can create static string field in Activity and set you String there.
You can do something like this:
in Activity
public static YourActivity mThis = null;
#Override
protected void onResume() {
super.onResume();
mThis = this;
}
#Override
protected void onPause() {
super.onPause();
mThis = null;
}
In your BroadcastReceiver:
#Override
public void onReceive(Context context, Intent intent) {
...
if (YourActivity.mThis != null) {
((TextView)YourActivity.mThis.findViewById(R.id.text)).setText("received c2dm");
}
else {
...
}

Categories

Resources