My application has the following modules,
To collect users CB location code.
To save that in a database of user's choice, say for example my CB code is 465783 and I can save that as 'College' in my database.
To provide alarm feature, in this module I can give a text input say I give it as 'College' and when the Cell Broadcast is updated if the value college matches alarm is given out.
Now, in my below code I've achieved first 2 modules and also the required database entries, databases search etc, I'm not able to read the updated CB location value.
public class Alarm extends MainActivity {
public String str;
public void onReceive(Context context, Intent intent) {
//---get the CB message passed in---
Bundle bundle = intent.getExtras();
SmsCbMessage[] msgs = null;
str = "";
if (bundle != null) {
//---retrieve the SMS message received---
Object[] pdus = (Object[]) bundle.get("pdus");
msgs = new SmsCbMessage[pdus.length];
for (int i=0; i<msgs.length; i++) {
msgs[i] = SmsCbMessage.createFromPdu((byte[])pdus[i]);
str += "CB " + msgs[i].getGeographicalScope() + msgs[i].getMessageCode() + msgs[i].getMessageIdentifier() + msgs[i].getUpdateNumber();
str += " :";
str += "\n";
}
}
}
EditText user_value;
Button startalarm;
Button stopalarm;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.third);
startalarm = (Button) findViewById(R.id.startalarm);
stopalarm = (Button) findViewById(R.id.stopalarm);
user_value = (EditText) findViewById(R.id.user_value);
final Ringtone ringtone;
ringtone = RingtoneManager.getRingtone(getBaseContext(), RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE));
startalarm.setOnClickListener(new View.OnClickListener()
{
public void onClick(View arg0)
{
// TODO Auto-generated method stub
if(user_value.length()==0)
{
Toast.makeText(getBaseContext(), "Please enter a value.", Toast.LENGTH_LONG).show();
}
Toast.makeText(getApplicationContext(), "alarm set", Toast.LENGTH_LONG).show();
//I want my alarm event to be started from here whenever a new CB sms arrives.
SQLiteDatabase aa = openOrCreateDatabase("MLIdata", MODE_WORLD_READABLE, null);
Cursor c = aa.rawQuery("SELECT CblocationName FROM MLITable WHERE CblocationCode = '"+str+"'", null);
c.moveToFirst();
c.getString(c.getColumnIndex("CblocationName"));
String sas = user_value.getText().toString();
if(sas.equals(c.getString(c.getColumnIndex("CblocationName"))))
{
//here comes the alarm code
if(ringtone == null)
{
Log.d("Debug", "ringtone is null");
}
else
{
ringtone.play();
}
}
}
});
stopalarm.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
ringtone.stop();
}
});
}
}
Detailed Explanation : whenever a user enters a new tower location he gets the updated Cell Broadcast message from the tower, so when this cbsms arrives I need to start my event of retrieving the CB area code and compare it with my database of area codes (which obviously have corresponding area code names set by the user) and when there is a match between the user given area name's corresponding area code with my current area code an alarm needs to be started, here I'm not able to do detect the arrival of updated location.
If further explanation is required of my problem statement, please comment.
From the comments received below, I've deduced that I'd need a receiver class, I've created one for my widget which does the same function (Displays the Cb location code on the widget), Now I do not how to activate that in my app.
My WidgetReceiver.java
public class CbReceiver extends BroadcastReceiver
{
public void onReceive(Context context, Intent intent) {
//---get the CB message passed in---
Bundle bundle = intent.getExtras();
SmsCbMessage[] msgs = null;
String str = "";
if (bundle != null) {
//---retrieve the SMS message received---
Object[] pdus = (Object[]) bundle.get("pdus");
msgs = new SmsCbMessage[pdus.length];
for (int i=0; i<msgs.length; i++) {
msgs[i] = SmsCbMessage.createFromPdu((byte[])pdus[i]);
str += "CB " + msgs[i].getGeographicalScope() + msgs[i].getMessageCode() + msgs[i].getMessageIdentifier() + msgs[i].getUpdateNumber();
str += " :";
str += msgs[i].getMessageBody().toString();
str += "\n";
abortBroadcast();
Toast.makeText(context, str, Toast.LENGTH_LONG).show();
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
RemoteViews remoteViews = new RemoteViews(context.getPackageName(),R.layout.widget);
ComponentName thisWidget = new ComponentName(context,MyWidget.class);
remoteViews.setTextViewText(R.id.update,str);
appWidgetManager.updateAppWidget(thisWidget, remoteViews);
}
}}
}
Help required.
Thank you.
Start your activity from your receiver on tower change. Use Intents to start your activity from receivers.
Ex: Refer this alarm example for above point, Alarm Example
Register your receiver in Android Manifest.xml.
Send a broadcast message from your receiver class also update your DB inside your receiver.
Catch the same in your activity. You can use Custom Broadcast for this.
Now activate your alarm in activity.
Hope these steps will help you. Refer the example I have mentioned.
Related
i have a background service which is working in background and looking for new SMS and creating notification and showing SMS
public class SmsBoradcast extends BroadcastReceiver {
private static final String SMS = "android.provider.Telephony.SMS_RECEIVED";
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(SMS)){
Bundle bundle = intent.getExtras();
if (bundle != null) {
Object[] pdus = (Object[])bundle.get("pdus");
final SmsMessage[] messages = new SmsMessage[pdus.length];
for (int i = 0; i < pdus.length; i++) {
messages[i] = SmsMessage.createFromPdu((byte[])pdus[i]);
}
// i want to save message some where befor showing notification
Notification notification = new Notification(context);
notification.sendNotification(context , "new message" , messages[0].getMessageBody());
}
}
}
}
everything is working and I'm receiving notification any time even if application is killed and its in background
now the question is that , how can I save those notifications when app is in background?
I tried room database and shared preferences in my service but not worked !!
**Please do not suggest using other methods. I just want to save data in background service , if its possible
You can create a Interface :
SmsListener
public interface SmsListener {
void onMessageReceived(String message);
}
add a Constructor to the SmsBoradcast and call it you recieve your add, then you can save your data from wherever you have started this broadcast.
I'm creating a simple Android application where I'm trying to intercept incoming SMS messages. The problem I am having is that the toast messages from the onReceive isn't showing up. Please help!
Thanks,
Isaiah Thompson
public class SMSR extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
//Print Message
Toast.makeText(context,"Received Message Start",Toast.LENGTH_SHORT).show();
// Get the data (SMS data) bound to intent
Bundle bundle = intent.getExtras();
SmsMessage[] msgs = null;
String str = "";
if (bundle != null) {
// Retrieve the SMS Messages received
Object[] pdus = (Object[]) bundle.get("pdus");
msgs = new SmsMessage[pdus.length];
// For every SMS message received
for (int i = 0; i < msgs.length; i++) {
// Convert Object array
msgs[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
// Sender's phone number
str += "SMS from " + msgs[i].getOriginatingAddress() + " : ";
// Fetch the text message
str += msgs[i].getMessageBody().toString();
// Newline <img draggable="false" class="emoji" alt="🙂" src="https://s.w.org/images/core/emoji/72x72/1f642.png">
str += "\n";
}
}
//Print Message
Toast.makeText(context,"Received Message End",Toast.LENGTH_SHORT).show();
Toast.makeText(context,str,Toast.LENGTH_SHORT).show();
}
}
Try this
new Handler(Looper.getMainLooper()).post(new Runnable()
{
#Override
public void run()
{
Toast.makeText(context, R.string.sent, Toast.LENGTH_SHORT).show();
}
});
Check out this answer
https://stackoverflow.com/a/11436473/6051131
also, make sure your priority (in the manifest file) is less than or equal 2147483647
My app is designed to append all scanned Bluetooth devices to a textview. This works great if the phones Bluetooth is on. However, if my app checks to see if the phones Bluetooth is off and turns it on if it is off, then start my the discovery process my broadcastreciever does not pick up an event and so my textview does not populate. Any help is appreciated!
Here is my code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_blue_tooth_main);
txtResults = (TextView) this.findViewById(R.id.txtResults);
mBlueToothAdapter = BluetoothAdapter.getDefaultAdapter();
if (!(mBlueToothAdapter.isEnabled())) {
mBlueToothAdapter.enable();
}
mBlueToothAdapter.startDiscovery();
MY RECEIVER:
public static class BlueToothBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
BluetoothDevice device = intent
.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
blueToothName = device.getName();
blueToothAddress = device.getAddress();
blueToothClass = device.getBluetoothClass();
blueToothBondState = device.getBondState();
GetBondStateStr(blueToothBondState);
blueToothUUIDS = device.getUuids();
paramsBlueTooth
.add(new BasicNameValuePair("Name: ", blueToothName));
paramsBlueTooth.add(new BasicNameValuePair("Address: ",
blueToothAddress));
paramsBlueTooth.add(new BasicNameValuePair("Class: ", String
.valueOf(blueToothClass)));
paramsBlueTooth.add(new BasicNameValuePair("Bond State: ",
blueToothBondStateStr));
paramsBlueTooth.add(new BasicNameValuePair("UUIDS: ", String
.valueOf(blueToothUUIDS)));
showBlueToothData();
}
ShowBlueToothData():
private void showBlueToothData() {
StringBuilder results = new StringBuilder();
results.append("-----BLUETOOTH DEVICE INFORMATION-----\n");
results.append("Name: " + blueToothName + "\n");
results.append("Address: " + blueToothAddress + "\n");
results.append("Class: " + blueToothClass + "\n");
results.append("Bond State: " + blueToothBondStateStr + "\n");
results.append("UUIDS: " + blueToothUUIDS + "\n");
txtResults.append(new String(results));
txtResults.append("\n");
}
Your chosen method of enabling the Bluetooth radio via the BluetoothAdapter.enable() method is an asynchronous call. As you can see from the method's documentation, you cannot assume that the radio is up and active as soon as the method returns. You have to wait for the ACTION_STATE_CHANGED broadcast to know that the radio is ready for you to try a scan.
If you read the documentation, notice also that doing it this was is a poor experience because there is no notification to the user. A better choice is the method of sending the user to Settings to enable Bluetooth themselves. You could modify your startup logic to be something more like this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_blue_tooth_main);
txtResults = (TextView) this.findViewById(R.id.txtResults);
mBlueToothAdapter = BluetoothAdapter.getDefaultAdapter();
…
}
#Override
protected void onResume() {
super.onResume();
if (!(mBlueToothAdapter.isEnabled())) {
//Take the user to settings first!
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivity(intent);
} else {
mBlueToothAdapter.startDiscovery();
}
}
This modification will check for Bluetooth every time you come to the foreground, and only trigger the scan if you are ready to do so.
Try doing:
Intent enable_intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enable_intent, REQUEST_ENABLE_BT);
inside if (!(mBlueToothAdapter.isEnabled())){...}
OR:
for(int i=0;i<5;i++){
if (!mBluetoothAdapter.isEnabled()) {
mBluetoothAdapter.enable();
}
Thread.sleep(100);
}else{
//display error, unsuccessfull , try manually
}
I'm trying to develop an android application that sends GPS coordinates via SMS with given time interval.
So I set up my main activity allowing the user to input a specific time in minutes. Transfer it to a alarmReceiver. Every alarm will request a locationupdate. And onlocationChanged will save it to the database before sending it via sms. I save it to the database before sending so that i will not lost any data if sending fails. I'm sending a message like this :
dbcon = new SQLController(ctx);
dbcon.open();
String SENT = "SMS_SENT";
final Cursor C = dbcon.readData_Location();
if(C.moveToFirst()){
getid = C.getString(0);
getLongitude = C.getString(1);
getLatitude = C.getString(2);
getTime = C.getString(3);
int id = Integer.valueOf(getid);
String phoneNo = "09061265887";
String msg = getLongitude +","+getLatitude+","+getTime;
Intent sendIntent = new Intent(SENT);
sendIntent.putExtra("loc_id", id);
PendingIntent sentPI = PendingIntent.getBroadcast(ctx, 0, sendIntent,0);
MainActivity.sendTextMessage(phoneNo, null, msg, sentPI, null);
}while(C.moveToNext());
The problem here is, it will send all the saved locations from the database continuously.
My plan is if the first sending fails, the sending using do-while loop must be stop.
I need to wait and check the result of sending process before sending another one. Im stock here and i dont know that to do. please help
MainActivity
public class MainActivity extends ActionBarActivity {
EditText et_timeinterval;
Button start,stop;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_timeinterval= (EditText) findViewById(R.id.editText1);
start = (Button) findViewById(R.id.button1);
stop = (Button) findViewById(R.id.button2);
start.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
int timeinminute = Integer.valueOf(et_timeinterval.getText().tostring());
Intent intent = new Intent(getBaseContext(),alarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(getBaseContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), timeinminute * 60 * 1000, pendingIntent);
Toast.makeText(ctx, "Alarm Started", Toast.LENGTH_SHORT).show();
}
});
}
public static void sendSMS(String phoneNumber,String message) {
SmsManager smsManager = SmsManager.getDefault();
String SENT = "SMS_SENT";
PendingIntent sentPI = PendingIntent.getBroadcast(basecontext, 0, new Intent(SENT), 0);
// ---when the SMS has been sent---
basecontext.registerReceiver(new BroadcastReceiver() {
#Override
public void onReceive(Context arg0, Intent arg1) {
switch (getResultCode()) {
case Activity.RESULT_OK:
Toast.makeText(basecontext, "SMS sent",
Toast.LENGTH_SHORT).show();
break;
case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
Toast.makeText(basecontext, "Generic failure",
Toast.LENGTH_SHORT).show();
break;
case SmsManager.RESULT_ERROR_NO_SERVICE:
Toast.makeText(basecontext,"No Service",Toast.LENGTH_SHORT).show();
break;
case SmsManager.RESULT_ERROR_NULL_PDU:
Toast.makeText(basecontext, "Null PDU",
Toast.LENGTH_SHORT).show();
break;
case SmsManager.RESULT_ERROR_RADIO_OFF:
Toast.makeText(basecontext, "Radio off",
Toast.LENGTH_SHORT).show();
break;
}
}
}, new IntentFilter(SENT));
// ---when the SMS has been delivered---
smsManager.sendTextMessage(phoneNumber, null, message, sentPI, null);
}
}
alarmReceiver.java
public class alarmReceiver extends BroadcastReceiver implements LocationListener{
private LocationManager locationManager;
private Context ctx;
SQLController dbcon;
String latitude,longitude,time;
#Override
public void onReceive(Context context, Intent arg1) {
// TODO Auto-generated method stub
ctx =context;
locationManager = (LocationManager) context
.getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1,1,this);
}
#Override
public void onLocationChanged(Location location) {
// TODO Auto-generated method stub
Time currentTime = new Time(Time.getCurrentTimezone());
currentTime.setToNow();
String latitude = ""+location.getLatitude();
String longitude = ""+location.getLongitude();
String time = currentTime.format("%k:%M:%S");
//inserting to database
dbcon= new SQLController(ctx);
dbcon.open();
dbcon.insertData(latitude, longitude, time);
//sending
String SENT = "SMS_SENT";
Cursor C = dbcon.readData_Location();
if(C.moveToFirst()){
String getid = C.getString(0);
String getLongitude = C.getString(1);
String getLatitude = C.getString(2);
String getTime = C.getString(3);
int id = Integer.valueOf(getid);
String phoneNo = "09061265887";
String msg = getLongitude +","+getLatitude+","+getTime;
MainActivity.sendSMS(phoneNo,msg);
}while(C.moveToNext());
locationManager.removeUpdates(this);
dbcon.close();
}
I want to do something like this
int result_code; //i want to get the resultcode from getResultCode()
C.moveToFirst();
do{
sendSMS(phonenum,sms);
//check first if sendSMS sending process is done before the next loop
}while(C.moveToNext() && result_code==0)
// result code 0 = send success 1=generic failure etc etc
This is not a simple problem. First, since you will want to wait, you need to do this on a background thread (using AsyncTask or a simple thread). Second, if you want it to continue trying/operating after the user exits the activity, you will need a service.
That said, you already have the code in place to check for the "sent" PendingIntent for the message. You need your thread/service to wait for the broadcast receiver responde from the sent message to get a response.
In your "sendSMS" method, you are registering a broadcast receiver to listen for the status of the SMS send. It will tell you whether the send was successful or not, and then you can either continue sending location updates, try again or whatever.
Like this:
basecontext.registerReceiver(new BroadcastReceiver() {
#Override
public void onReceive(Context arg0, Intent arg1) {
switch (getResultCode()) {
case Activity.RESULT_OK:
Toast.makeText(basecontext, "SMS sent",
Toast.LENGTH_SHORT).show();
// add code here to send next message
break;
case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
Toast.makeText(basecontext, "Generic failure",
Toast.LENGTH_SHORT).show();
// add code here to try again or wait
break;
case SmsManager.RESULT_ERROR_NO_SERVICE:
Toast.makeText(basecontext,"No Service",Toast.LENGTH_SHORT).show();
// add code here to try again or wait
break;
case SmsManager.RESULT_ERROR_NULL_PDU:
Toast.makeText(basecontext, "Null PDU",
Toast.LENGTH_SHORT).show();
// add code here to try again or wait
break;
case SmsManager.RESULT_ERROR_RADIO_OFF:
Toast.makeText(basecontext, "Radio off",
Toast.LENGTH_SHORT).show();
// add code here to try again or wait
break;
}
}
}, new IntentFilter(SENT + someMessageId));
Your intent filter also needs to identify the message (where I added "someMessageId") if you send more than one SMS before waiting for the receiver to respond.
I have an app that listens to incoming messages, and if the originating sender is the one specified by the user, it then reacts accordingly, showing a special alert and aborting the broadcast, preventing it from reaching the inbox. On Verizon, it works perfectly. I've sent over 300 without any issue, as have a few other testers.
On any other carrier though, it's a mess.
On AT&T, the broadcast is never aborted and it shows up in the sms inbox.
On Sprint, the broadcast is aborted, but it never gets beyond that. The AlertActivity intent is never called, nor either of the toast messages I put to check.
On T-Mobile, the broadcast is never aborted and it shows up in the sms inbox.
I have the receiver done in java rather than registered in the Manifest because I register it in a service which is started on app launch and on BOOT_COMPLETED.
Service
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
public void startService() {
IntentFilter SMSfilter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
this.registerReceiver(Receiver.br, SMSfilter);
}
Receiver
static public BroadcastReceiver br = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
if (bundle != null) {
Object[] pdus = (Object[]) bundle.get("pdus");
final SmsMessage[] messages = new SmsMessage[pdus.length];
for (int i = 0; i < pdus.length; i++) {
messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
if (messages[i].getOriginatingAddress().equals(Test.SENDER)) {
abortBroadcast();
String[] body = messages[i].getDisplayMessageBody().split(" ", 7);
if (body[0].equals("test")) {
test = true;
}
cat = body[1];
level = body[2];
urgency = body[3];
certainty = body[4];
carrier = body[5];
message = body[6];
intent = new Intent(context, AlertActivity.class);
Bundle b = new Bundle();
b.putString("title", cat);
b.putString("certainty", certainty);
b.putString("urgency", urgency);
b.putString("level", level);
b.putString("message", message);
b.putBoolean("test", test);
intent.putExtras(b);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); TelephonyManager manager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
carrierName = manager.getNetworkOperatorName();
if (carrierName.replaceAll(" ", "").equals(carrier)) {
context.startActivity(intent);
} else {
//testing
toast(carrierName.replaceAll(" ", ""), context);
}
}
}
}
}
};
I use these imports in the app,
import android.telephony.SmsMessage;
import android.telephony.TelephonyManager;
I know that there is a gsm version of these as well, which I don't use. Could this be why the app isn't detecting the incoming messages on the gsm carriers?
UPDATE 1
According to http://developer.android.com/reference/android/telephony/gsm/package-summary.html its not due to not using the gsm specific imports.
ANSWER
Got it.
It has to do with how the incoming message senders number is read.
On the verizon device it would register as xxxxxxx on others, +1xxxxxxx. Added an option to acces Test.SENDER or Test.SENDER_LAME which is +1xxxxxxx
Got it. It has to do with how the incoming message senders number is read. On the verizon device it would register as xxxxxxx on others, +1xxxxxxx. Added an option to acces Test.SENDER or Test.SENDER_LAME which is +1xxxxxxx