Automatically launching Android app or service when Bluetooth connection is made? - android

When my app or service is running, I can offer a Bluetooth profile (e.g. SPP, DUN, or my own UUID) using BluetoothAdapter.listenUsingRfcommWithServiceRecord(...).
Is it possible to instead have this Bluetooth profile visible on the device all the time, even when my app or service is not running, and have Android launch my app or service automatically when someone connects to this Bluetooth profile?
I could envision something like this inside AndroidManifest.xml:
<receiver android:name="com.example.MyBluetoothReceiver" android:exported="true">
<intent-filter>
<action android:name="android.bluetooth.adapter.action.RFCOMM_ACCEPT" />
<data android:name="My SPP Service"
android:uuid="00001101-0000-1000-8000-00805F9B34FB" />
</intent-filter>
</receiver>
The goal would be for the Android framework to recognize this receiver purely based on AndroidManifest.xml, automatically offer the Bluetooth profile as specified in the <data ...>-tag whenever the Bluetooth radio is turned on, and then instantiate and call my intent receiver whenever an actual connection is made. This would be similar to the way custom URL handlers work by registering an ACTION_VIEW intent with CATEGORY_BROWSABLE, which the browser then calls to launch my app, even if my app is not currently running.
The closest I could find so far are notifications for general Bluetooth status changes (radio on/off, device paired), e.g. here:
Android Broadcast Receiver bluetooth events catching, or the BluetoothAdapter's ACTION_CONNECTION_STATE_CHANGED intent, which is called for connection to an existing remote profile, rather than a newly offered local one.

Ya its possible in your onReceive() need to add below code to launch the app.
PackageManager pm = context.getPackageManager();
Intent launchIntent = pm.getLaunchIntentForPackage("com.example.blutoothapp");
launchIntent.putExtra("some_data", "value");
context.startActivity(launchIntent);
Hope this will help.

Related

Communication between two closed android applications

I have 2 apps on one device. The server sends push to both applications. I want the first application that received the push to show a notification, and the second should do nothing. How can I check that the first app already showed a notification?
Apps can be closed. I use FirebaseMessagingService for wake up.
I need this because the user can have only one app installed or both.
Best way is just your server send notification to only one app. But if it is not possible, you can use Broadcast receiver I think.
You can use Broadcast receiver to communicate between two application.
In app B, for example declare broadcast receiver like follow:
<receiver android:name=".MyBCReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="what.ever.you.want" />
</intent-filter>
</receiver>
And from app A.
Intent intent = new Intent();
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
intent.setAction("what.ever.you.want");
intent.putExtra("key","data");
intent.setComponent(new ComponentName("com.app.b","com.app.b.MainActivity"));
sendBroadcast(intent);
Then your app B, you can just make a mark using sharedPreference to not make a notification again.

Launch activity by dialing a number

I've created an appropriate BoradcastReceiver, registered it in Manifest.xml and here is my problem: if my application has already been launched and hanging in background, then dialing a number would bring it to front. If it has not been launched then dialing a number would have no effect.
How can I fix this? I test this on Xiaomi Mi4 with MIUI6 if that's important.
Here's the code (I use Scala):
manifest.xml:
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
...
<receiver android:name="DialerGate" android:enabled="true" android:exported="true">
<intent-filter android:priority="1">
<action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
</intent-filter>
</receiver>
BroadcastReceiver:
class DialerGate extends BroadcastReceiver {
def onReceive(context: Context, intent: Intent) =
if (intent.getAction equals Intent.ACTION_NEW_OUTGOING_CALL) {
val phoneno = intent.getExtras getString Intent.EXTRA_PHONE_NUMBER
val prefs = context.getSharedPreferences("prefs", Context.MODE_PRIVATE)
val number = prefs.getString(AbstractKit.LAUNCH_NUMBER, null)
Log.d("WALLET-PHONE", s"Dialed number: $phoneno, saved number: $number")
Log.d("WALLET-PHONE-OK", (number == phoneno).toString)
val i = new Intent
i.setClassName("com.app.wallet", "com.app.wallet.MainActivity")
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP)
val appContext = context.getApplicationContext
appContext.startActivity(i)
//if (number == phoneno) context startActivity new Intent(context, target)
//context stopService intent
}
}
From a simple user perspective, that cannot be done (its a security feature).
Starting from HONEYCOMB Android doesn't allow any broadcast receivers to be invoked until application is run at least once.
Its basically simpler to allow the program to be run at least once (during boot its the most common one), and then have the intent close the app if its not the time to use it.
Check this for further details on how to implement additional receivers that may do what you need it to do.
create a Listener in your Broadcast Receiver and listen to ON_BOOT_COMPLETED, then start your app, in silent mood and you will be resolved to your normal workings.
side note If Activities was to be waken up that way, then Keylogging apps and hacking apps will be very very very cheap to create - hence make android vulnerable.
http://android-developers.blogspot.in/2013/05/handling-phone-call-requests-right-way.html
Listening for outgoing call requests
Apps that provide phone calling services (such as VOIP or number management) can set up Intent filters to handle outgoing call requests, such as those made from the Dialer or other installed apps. This provides a seamless integration for the user, who can transition directly to the calling service without having to redial or launch another app.
When the user initiates a call, the system notifies interested apps by sending an ordered broadcast of the NEW_OUTGOING_CALL Intent, attaching the original phone number, URI, and other information as extras. This gives apps such as Google Voice and others a chance to modify, reroute, or cancel the call before it’s passed to the system’s default phone app.
If you want your phone calling app to be able to handle outgoing call requests, implement a broadcast receiver that receives the NEW_OUTGOING_CALL Intent, processes the number, and initiates a call as needed. Make sure to declare an intent filter for NEW_OUTGOING_CALL in the receiver, to let the system know that your app is interested in the broadcast. You’ll also need to request the PROCESS_OUTGOING_CALLS permission in order to receive the Intent.
Note that the system broadcasts NEW_OUTGOING_CALL only for numbers that are not associated with core dialing capabilities such as emergency numbers. This means that NEW_OUTGOING_CALL can not interfere with access to emergency services the way your use of CALL_PRIVILEGED might.
Here’s an example broadcast receiver declared in an app’s manifest file:
<manifest>
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<application>
...
<receiver android:name=MyOutgoingCallHandler">
<intent-filter>
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
...
</application>
</manifest>
And I am sure that <category android:name="android.intent.category.DEFAULT" /> will do the trick for you. check this question too for more details about category tag.here
You could try a few things.
Try using java, if not try the following.
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
...
<receiver android:name="DialerGate">
<intent-filter android:priority="2147483648">
<action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
</intent-filter>
</receiver>
Changed priority and removed unnecessary stuff.
Also though I am good at Broadcast Receivers I don't have experience in Scala, so I can only suggest a few ideas. Remove the if statement. It is not required as you have already have an <intent-filter>. Also change the intent as in the paste bin code.
Have a look here.
You may use a service, but just care about one thing: when the app is closed the service get closed also because they are in a one thread, so the service should be on another thread in order fot it not to be closed
You can keep it alive with AlarmManager.
In the link there are also some samples :)
Hope it helps!
The application might not have the permissions to the "phone", either ask for permissions at runtime or go to application settings and enable all the permissions asked by the application.
This worked for me..

How does FitBit manage to totally take over NFC?

The FitBit app just introduced its new NFC functionality and now, even though my app, and several other apps I have installed on my device are all registered (in the manifest) as NFC apps, Android no longer asks me which app I'd like to use and just goest straight to FitBit when I scan the NFC tag to my devices.
I'm curious what they could be doing to override the settings in the manifest. Is there some way that they can be running a Service that dominates NFC and swallows all incoming NFC intents?
I'm hoping there's some way to undermine what they're doing cause currently, in effect, their app is malware that breaks the underlying basic NFC functionality on Android.
A service cannot receive NFC intents, so that cannot be the cause of what you see. As far as I can tell, the FitBit app filters for NFC events with MIME type "text/plain". So if your NFC tag contains an NDEF text record, it will likely start FitBit or, if more apps are installed with the same intent filter for NFC and "text/plain", an app chooser is shown for the relevant apps.
Try scanning another tag with different content or change the content on your tag to a different type of NDEF message and see what happens.
I have an app with a specific intent filter for one of its activities:
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="duckapp" />
</intent-filter>
If a scan a tag with an URL starting with duckapp://, my app's activity is started directly even though I have other NFC apps such as TagInfo installed.
I don't know for sure. But it seems that if one activity has a more specific intent filter than all the other apps, it's directly started.
If anybody knows about a precise documentation of this mechanism, I'd be glad to hear about it.

What determines app auto start on boot in Android?

In my application, there's a feature that allows users to dial a specific number and brings up an activity to front. I have the following receiver, and the only receiver registered in AndroidManifest.xml.
<receiver android:name="com.example.myapp.OutgoingCallListener" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
</intent-filter>
</receiver>
Please note there's no BOOT_COMPLETED intent or service.
Now here's the thing I couldn't figure out. When I reboot my device, go check the Running Apps, my application is not listed there. But, if I dial the specific number, my application starts and the activity is brought to front.
My question is: If the app is not a service, and not started on boot, how could it recieve intent from Android? That is, in my case, how could my app listen to NEW_OUTGOING_CALL while it's not started at all?
A BroadcastReceiver that is registered in the manifest is always capable of responding to a matching broadcast. If your process is not running for any reason, Android will start up a process for you.

Broadcast receiver not receiving intent

I have two apps that I have complete control over. Both are signed with the same cert and both use the exact same intent filter. One sends the broadcast from a fragment, the other is suppose to receive it and do something. This however is not working:
Strings.FILTER_INIT_REGISTER = "com.app.FILTER_INIT_REGISTER"
Intent intent = new Intent(Strings.FILTER_INIT_REGISTER);
getActivity().sendBroadcast(intent);
I have registered the receiver in the Manifest app tag for the app containing the ReportingReceiver class:
<receiver
android:name=".receivers.ReportingReceiver"
android:exported="true"
>
<intent-filter>
<action android:name="com.app.FILTER_INIT_REGISTER" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
Curious why the ReportingReceiver class is not getting the intent call?
If your application only has a service and receivers then this won't work in Android 3.1 and later. The reason is that the system will not send broadcast Intents to application that are in the STOPPED STATE. An application is in the STOPPED STATE when it is first installed. It is removed from the STOPPED STATE when the user manually starts the application for the first time. It is returned to the STOPPED STATE if the user forces the application to stop using the application manager tool.
Since your application has no Activities, there is no way for the user to "start" it. Therefore it will never come out of the stopped state.
See http://developer.android.com/about/versions/android-3.1.html#launchcontrols
As Android Addict says in his comment to David Wasser's answer ... there is a way around this behaviour.
Just add the following flag to the calling Intent. This will ensure that you also reach broadcast receivers from "stopped" applications.
http://developer.android.com/reference/android/content/Intent.html#FLAG_INCLUDE_STOPPED_PACKAGES
You can read more about this Android 3.1 change here
http://developer.android.com/about/versions/android-3.1.html#launchcontrols
and here
http://code.google.com/p/android/issues/detail?id=18225

Categories

Resources