So last week my phone got stolen and the wifi and mobile data were turned off so I had no access to it. GPS was turned off as well but that's of no use if the phone doesn't have an internet connection. Even though the phone was protected by a fingerprint and my data would be safe, I still would've loved that phone back. Thinking about this I came up with an idea.
What if I create an Android app that would run silently in the background on my (new)phone and would do absolutely nothing. All it would do is listen for a certain string of characters in all the SMS the phone receives.
Now say my new phone gets stolen too (talk about tough luck). I immediately call at my number from someone's phone. If the phone is still turned on and has cellular connectivity, I would send an SMS with THAT string of characters to my number.
As soon as the phone receives the SMS, the app picks up on it and does the following:
Turns on GPS.
Gets a lock on its position.
Starts sending its own coordinates to the number it received the SMS from at
a rate of once every minute via SMS.
This way I get to know where my phone is and the thief won't know whats happening because everything is being done silently and the phone is locked as well. The main thing I want to cover with this app is the fact that this doesn't rely on an internet connection. It just trusts the fact that only I know the certain string of characters and that the app exists and is running 24/7. I know this isn't suitable for public use but for personal use, its ok I guess.
What I want to ask for is advice on what approach should I take? Any suggestions about things I should add? Have you ever tried something like this and if so, then can you share your experience with me?
Thanks in advance!
I have done in my project. Hope it will help you. Ask if it not clear to you. First you need to create SMSReceiver class for receiving sms into application which extend broadcast receiver & SMSListener interface for listening the SMS data and pass it to your desired activity.
Here is the code:
public class SmsReceiver extends BroadcastReceiver {
private static SmsListener mListener;
#Override
public void onReceive(Context context, Intent intent) {
Bundle data = intent.getExtras();
Object[] pdus = (Object[]) data.get("pdus");//pdus is the protocol of SMS data.
for(int i=0;i<pdus.length;i++){
SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) pdus[i]);
String sender = smsMessage.getDisplayOriginatingAddress();
//You must check here if the sender is your provider and not another one with same text.
String messageBody = smsMessage.getMessageBody(); //SMS text data
mListener.messageReceived(messageBody);//Pass on the text to our listener.
}
}
public static void bindListener(SmsListener listener) {
mListener = listener;
}
public static void unbindListener() {
mListener = null;
}
public interface SmsListener {
void messageReceived(String messageText);
}
}
Then you need to declare your receiver in manifest file. Like below.
<receiver android:name=".SmsReceiver" android:permission="android.permission.BROADCAST_SMS">
<intent-filter android:priority="999">
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
Then finally in your activity add this code for getting SMS data.
public Pattern p = Pattern.compile("(|^)\\d{4}"); //It will detect 4 number OTP value.
SmsReceiver.bindListener(new SmsListener() {
#Override
public void messageReceived(String messageText) {
Log.d("MESSAGE TEXT",messageText);
if(messageText != null)
{
Matcher m = p.matcher(messageText);
if(m.find()) {
//Do your code here after your sms received.
}
else
{
//Do here if you want to trigger anyof sms received.
}
}
}
});
BroadcastReceiver always listening for the incoming SMS. If it fails to trigger at app close or screen close state or always running issue look at this solution will help you.
Keep broadcast receiver running after application is closed
EDITED
Have a look at some workground scenario of never end service. All you need is monitoring the service & restart if killed. Also you can store the status of service in shared preference as well. Here some of the options & workcode for never end service. You can find more on search.
Android: keep Service running when app is killed
Creating a never ending background service in Android
Hope it will helps.
Related
I am developing a custom telephony application that is able to receive calls.
Using this code for handling the incoming call
https://code.google.com/p/auto-answer/source/browse/trunk/src/com/everysoft/autoanswer/AutoAnswerIntentService.java
Unfortunately my app loses focus on the incoming call.
THIS was a partial solution for outgoing calls
Android- Telephone app that keeps focus on outgoing & incoming phoneCall
What about incoming calls? How do I keep focus in my custom app?
I am guessing this might involve downloading and modifying the source code as simply accessing the SDK gives little control over the built-in phone application.
Since the reference you made about outgoing calls is acceptable, then you can place an activity in front of the incoming call screen shortly after it displays. The difficulty in doing this is that the call state will change to "RINGING" and then also "OFFHOOK" but the phone has not displayed the InCallScreen when these are broadcast.
Like the post you referenced, this solution does not actually embed the phone feature into the app (like a webview for web browsing) but rather places an activity in front of the InCallScreen shortly after it displays.
For incoming calls, you need to delay the launch of your activity, like in this post:
Android - Customised New Incoming Call Screen
You can put anything on the screen at the point, the hard part is determining the lag time so that it meets your needs (slow enough so that the InCallScreen has a chance to launch but fast enough to be minimally disruptive).
Beyond that, even extending AOSP will not help unless you have access to each physical device where this will be used to root them or put a custom build on them. Access to the PhoneApp features is not accessible to non-system apps (the com.android.phone package).
Mention the below broadcast receiver in manifest.xml file.
<receiver android:name="com.example.incomingcall.IncomingCallReceiver" >
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
IncomingCallReceiver.java:
public class IncomingCallReceiver extends BroadcastReceiver{
public void onReceive(Context context, Intent intent) {
Bundle extras = intent.getExtras();
if (extras != null) {
String state = extras.getString(TelephonyManager.EXTRA_STATE);
if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
Thread thread = new Thread(){
private int sleepTime = 400;
#Override
public void run() {
super.run();
try {
int wait_Time = 0;
while (wait_Time < sleepTime ) {
sleep(100);
wait_Time += 100;
}
}catch (Exception e) {
Toast.makeText(context,
"Error Occured Because:" + e.getMessage(),
Toast.LENGTH_SHORT).show();
}
context.startActivity(new Intent(context,CustomActivity.class)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
}
};
thread.run();
}
}
}
}
I Have an app that is showing a toast when receiving broadcast and action equals BluetoothAdapter.ACTION_STATE_CHANGED, everything is working OK, but the problem here is that I want to do something when bluetooth is turning on but when bluetooth is activated from a button of the launcher it seems like the broadcast is arriving late or my app is receiving late or something like that, because when I started Bluetooth from other app, the receiver works great and on time.
Any suggestion in what is the problem? I have the receiver registered in manifest.
and it seems that sometimes loops infinitely because I have two toast to show when bluetoothAdapter.ACTION_STATE_CHANGED and it shows infinitely
Any idea of why is happening this and previous things?
Receiver:
public class Receivers extends BroadcastReceiver {
protected static AlertObject BTTurningOn = new AlertObject();
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
final String action = intent.getAction();
this.context=context;
if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
BluetoothAdapter.ERROR);
if(state == BluetoothAdapter.STATE_TURNING_ON && BTTurningOn.Activated == true)
{
Alert(BTTurningOn);
}
}
}
BTTurningOn is just an object with some boolean variables to know whether to attend the broadcast message or not
Here is the important part of manifest:
<receiver android:name=".Receivers">
<intent-filter>
<action android:name="android.bluetooth.adapter.action.STATE_CHANGED" />
</intent-filter>
</receiver>
When I start the bluetooth from my other app or from Adjusts/ wireless connections it works great, but its not working when I start it from an icon of the launcher or the upper bar where notifications appear, Im using GO Launcher EX Version 2.76
My other app get the broadcast and works great from the site that this app is not getting, but the difference is only where I register the receiver, this app is in MAnifest and other app is on one Activity
The answer is: I did not have the bluetooth permission in manifest, but it's kinda strange because it did not receive broadcast messages when originated from Launcher but actually the app received them when originated from my other app
I am working on an Android application, having functionality like voicemail.
I am using BroadcastReceiver to get dialing events.
I have to get the event "WHEN CALL IS UNANSWERED (not picked after few rings) FROM RECEIVER".
I will do some actions on caller end against this event.
I am using AVD emulator, and
I do call from one instance to another instance and it calls perfectly,
but the problem is: It continuously calls until I reject or accept the call.
This way I cannot detect that "CALL IS UNANSWERED AFTER A NUMBER OF RINGS".
So I want the Caller emulator to drop the call after a number of rings (if unanswered) like a normal phone.
I can do it (drop the call after some time) by writing some code, but I need the natural functionality of phone in the emulator.
Can anyone please guide me? Is there any settings in the emulator? Or something else?
The code is shown below in case it helps:
public class MyPhoneReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent)
{
Bundle extras = intent.getExtras();
if (extras != null)
{
String state = "my call state = " + extras.getString(TelephonyManager.EXTRA_STATE);
Log.w("DEBUG", state);
}
}
Hi i think this is impossible with reference to the link:
http://android.bigresource.com/Track/android-sr1t1eagx/
Regards
At the moment I am developing an application which catches the action NEW_OUTGOING_CALL with the help of a BroadcastReceiver. I am aborting the call by calling setResultData(null). After that I am showing the user a dialog which allows him to decide if he wants to use my application to rewrite its number. When the users decision has happened I am placing the new call depending on the decision. Now my broadcast receiver gets called up once again.
What is the correct way of getting to know that I have already processed the number? I got a working solution that uses a timestamp to guess if it could be already processed. Another solution would be to add a "+" at the end of the processed number.
These methods are working fine for my application being the only one catching the NEW_OUTGOING_CALL event. But what should I do when other applications (like Sipdroid or Google Voice) are also sitting there catching the NEW_OUTGOING_CALL broadcast aborting it and restarting it again? I don't see a possibility to get to know if we are still in the same "call flow" and if I already processed the number.
I would love to hear your ideas about this problem!
What API level are you working with? If it's >= 11, check out the new BroadcastReceiver.goAsync function that lets you extend the processing of the broadcast outside of the onReceive function of your receiver. This could bypass the need to loop altogether.
If, like me, you're stuck trying to do this before level 11, it is surprisingly tricky to do this elegantly. You may have done this as well, but I tried to include a "processed" flag as an extra in the ACTION_CALL intent that my code generated, hoping that it would somehow get included in the resulting ACTION_NEW_OUTGOING_CALL broadcast, but that sadly does not work.
The best solution I have been able to find is including a fragment in the URI for the ACTION_CALL intent that you generate. This fragment will be included for the resulting ACTION_NEW_OUTGOING_CALL broadcast, so your broadcast receiver can differentiate between the original call and the one that you generate, but it won't interfere with handlers that aren't looking for it.
Here's the basic code.
In your BroadcastReceiver for the ACTION_NEW_OUTGOING_CALL
public class YourBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// extract the fragment from the URI
String uriFragment = Uri.parse(
intent.getStringExtra("android.phone.extra.ORIGINAL_URI")).getFragment();
// if the fragment is missing or does not have your flag, it is new
if (uriFragment == null || !uriFragment.contains("your_flag")) {
// launch your activity, pass the phone number, etc.
// use getResultData to get the number in order to respect
// earlier broadcast receivers
...
// abort the broadcast
this.setResultData(null);
this.abortBroadcast();
}
// otherwise, your code is there, this call was triggered by you
else {
// unless you have a special need, you'll probably just let the broadcast
// go through here
// note that resultData ignores the fragment, so other receivers should
// be blissfully unaware of it
}
}
}
When the user first dials the number, the fragment will either be missing altogether or your flag won't be present, so you'll abort the broadcast and start your activity. In your activity, if you decide to place the call again, do something like the following:
startActivity(new Intent(Intent.ACTION_CALL,
Uri.parse("tel:" + modified_number + "#your_flag")));
The "your_flag" fragment will then be present in the subsequent NEW_OUTGOING_CALL broadcast and thus allow you to handle this case differently in your broadcast receiver.
The nice thing about this is the the fragment is completely ignored unless you look for it in the ORIGINAL_URI, so other broadcast receivers can continue to function. If you want to be really nice, you may want to look for an existing fragment and add your flag to it (perhaps with a comma separator).
I hope that helps. Good luck!
I don't see a possibility to get to
know if we are still in the same "call
flow" and if I already processed the
number.
Technically, you are not in the same "call flow" as placing a new call is asynchronous. You have to use hints (such as a timestamp) as you seem to be doing already.
If you are confident that other applications will not rewrite the number except to change the prefix or to add a suffix, you may want to add another "proximity check" hint to avoid false positives/negatives, but I'm afraid that's about all you can do.
The onReceive() method in Broadcast receiver receives an Intent as an argument.
Extract the Bundle from the Intent using Intent.getExtras().
This Bundle contains 3 key-value pairs as follows :
android.phone.extra.ALREADY_CALLED = null
android.intent.extra.PHONE_NUMBER = 98xxxxxx98
android.phone.extra.ORIGINAL_URI = tel:98xxxxxx98
98xxxxxx98 is the number dialled by the user.
When the onReceive() is called again, this number changes to 98xxxxxx98* or 0*
By checking for the asterisk(*) at the end of the dialled number, it can be inferred if the onReceive() method is called for the first time or the next subsequent times.
One of the answers would be to track the boolean extra in the intent. It is done in similar way by the Google Phone app. You can check this BroadcastReceiver here (look for alreadyCalled usage)
The other way would be just to pass that "rewritten" number from your broadcast to the next broadcast receiver down the road (can be any app, like Sipdroid, Google Voice, or custom VoIP app) without calling ACTION_CALL intent (this is why you get loop and you broadcast receiver called again) The following code is example of how I am handling call in my custom VoIP app. When I intercept NEW_OUTGOING_CALL in my broadcast receiver, I first check if there is internet connection. If phone is connected to internet I use custom defined intent action of my activity to place call through my VoIP app. If there is no internet connection, I just set original phone number to the broadcast receiver result data. This is used by the next broadcast receiver (probably default phone app, but doesn't have to be) in the flow to place a call.
public class BHTTalkerCallReceiver extends BroadcastReceiver {
private static final String TAG = "BHTTalkerCallReceiver";
#Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "Broadcast successfull ... ");
// Extract phone number reformatted by previous receivers
String phoneNumber = getResultData();
if (phoneNumber == null) {
// No reformatted number, use the original
phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
}
if (isNetworkAvailable(context)) { // Make sure this app handles call only if there is internet connection
// My app will bring up the call, so cancel the broadcast
setResultData(null);
// Start my app to bring up the call
Intent voipCallIntent = new Intent(context, TalkerActivity.class);
voipCallIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
voipCallIntent.putExtra(TalkerActivity.OUT_CALL_NUMBER, phoneNumber);
voipCallIntent.setAction(TalkerActivity.BHT_TALKER_OUT_CALL);
context.startActivity(voipCallIntent);
} else { //otherwise make a regular call...
// Forward phone data to standard phone call
setResultData(phoneNumber);
}
}
private boolean isNetworkAvailable(final Context context) {
final ConnectivityManager connectivityManager = ((ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE));
return connectivityManager.getActiveNetworkInfo() != null && connectivityManager.getActiveNetworkInfo().isConnected();
}
}
Looking through forums, it seems that there is not a way to end calls, but on the Android Developers page, the permission PROCESS_OUTGOING_CALLS "Allows an application to monitor, modify, or abort outgoing calls." I can't find any documentation on how to end a call even with this permission. Is this possible, or is it just a mistake on the page?
http://developer.android.com/reference/android/Manifest.permission.html#PROCESS_OUTGOING_CALLS
The attention is not to end call that is already started, but to drop the call before that was started. The meaning is - you dial some number , press send , program receives the call request and aborts it , so the call never starts. It is also possible just to change the phone number (to extend short numbers to full one, etc.) and pass the call.
It works fine:
public class phoneReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_NEW_OUTGOING_CALL)) {
abortBroadcast();
if (getResultData()!=null) {
String number = null;
setResultData(number);
}
}
}
}