Android: Why intent doesn't received by broadcastreceiver? - android

I have a few intents that activity sends to service.
All of those are registered in manifest:
<service android:name=".location.LocationService" android:label="#string/location_service_started">
<intent-filter>
<action android:name="#string/location_service_set" />
<action android:name="#string/location_service_start" />
<action android:name="#string/location_service_stop" />
</intent-filter>
</service>
But only location_service_start and location_service_stop intents are received. What could be the reason?
There is my receiver code:
private BroadcastReceiver LocationServiceReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(getString(R.string.location_service_stop)))
{
showMessage("stop");
}
if(intent.getAction().equals(getString(R.string.location_service_start)))
{
showMessage("start");
}
if(intent.getAction().equals(getString(R.string.location_service_set)))
{
showAlertBox("set");
}
}
};
So I never see "set" message. I've even tried put sendBroadcast for "start" and "set" messages in the same place, but everything still the same. "start" - OK, "set" - never received.
Functions that fires intents:
protected void start()
{
Intent intent = new Intent(getString(R.string.location_service_start));
getApplicationContext().sendBroadcast(intent);
}
protected void set(double lat, double lon, double rad)
{
Intent intent = new Intent(getString(R.string.location_service_set));
intent.putExtra("lat", lat);
intent.putExtra("lon", lon);
intent.putExtra("rad", rad);
getApplicationContext().sendBroadcast(intent);
}
Both are correct send, without errors, actions are correct.
UPD:
Oh, my fault. I forgot to add filter.addAction... for new intent.
I'm sorry. But answers was really useful! Thank you!

All of those are registered in manifest:
Generally, you do not use string resources for action strings in an <intent-filter>, because you never want to internationalize them.
Generally, you do not use an <intent-filter> at all with a service unless you are exposing that service to third-party apps. In fact, right now, you are exposing your service to third-party apps, so anyone can send these commands to your service.
But only location_service_start and location_service_stop intents are received
No, none of them are received by the service. You are sending broadcasts in the Java code. Services do not receive broadcasts.
Functions that fires intents:
Do not use getApplicationContext() unless you know what you are doing. Whatever you are calling getApplicationContext() on is a Context, so you can just call sendBroadcast() on it.

Copy & Paste from this question I just answered. Should be the same issue.
You have to put each <action /> tag inside a seperate <intent-filter /> tag in your manifest.
This should be a bug, since the doc states you can put more than one action inside a filter tag:
Zero or more action [..] tags should be included
inside to describe the contents of the filter.
Source

Related

Android Intent reopening activity

I have an issue that I have not found a solution to on this site, but if this is a duplicate question, I apologize.
I am developing an application that serves as a terminal for registering when employees start/finish work, among numerous other things. The way it works is that with NFC switched-on, they scan their NFC cards and my app reads them and ultimately sends the appropriate information to the server.
However, if the app is already open (it's supposed to be open all the time, so this is an issue) and an NFC card is scanned, it reopens the app. Of course, this is done because I have set it that way in the manifest. But I can not find a way to have my app recieve the NFC scan intent if I do not add all of these lines in the manifest:
<intent-filter>
<action android:name="android.nfc.action.TAG_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
I have tried just writing without the but in that case it does not read the card, but instead the program chooser comes up on the phone, or if the phone does not have an appropriate app it simply says "NFC read error".
Does anyone have a solution for this? This is the last step in my project, and I have had a lot of trouble with it, and would appreciate any help. It's probably something simple that I'm just not seeing, but I'd appreciate it either way.
Android activities have different launch modes. If you set single instance it will use already opened activity and doesn't create a new activity. You can read the new intent in override method onNewIntent()
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
// read intent values here
}
For various activity elements
You can use broadcastReceiver,
- first initiate the receiver to your activity
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("whateveryouwant");
notificationBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// here you can read the intent and customize the action;
int usage = intent.getIntExtra("usage",1000);
}
}
};
second register the broadcast
registerReceiver(notificationBroadcastReceiver,intentFilter);
At end unregister to the broadcast in the onDestroy method
#Override
protected void onDestroy() {
if(notificationBroadcastReceiver != null){
unregisterReceiver(notificationBroadcastReceiver);
notificationBroadcastReceiver = null;
}
super.onDestroy();
}
after doing that instead of intenting activity you can sendBroadcast()
a little guide: https://developer.android.com/reference/android/content/BroadcastReceiver.html
hope it will be helpfull

Android Hidden App start from dialer

We can hide the android app from launcher by editing manifest XML,but is there any code snippet or example by which we can hide the app and start it by entering some code like ##4444## like that.Any way to do this??
Thanks in advance.
To start your app from dialer you need to do three things:
1. Add receiver to your AdroidManifest.xml
<receiver android:name="com.example.HiddedReceiver">
<intent-filter>
<action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
</intent-filter>
</receiver>
2. Create BroadcastReceiver as stated in xml. It will intercept EVERY calls number. You just need to scan it for your string and do apropiate action - in this case fire off an intent.
public class HiddenReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(android.intent.action.NEW_OUTGOING_CALL)) {
String resultData = getResultData();
if (resultData != null) {
if (resultData.contains("YOURCODE")) {
setResultData(null); // it wont continue calling that number
//HERE CREATE your intent
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
}
}
}
}
3. To get this working, you need to tell android you will be using this feature, and to grant permission to process calls from the user at install time.
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
i didnt test it, but this one works like a charm:
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>

Android re-enable a disabled App upon installation of update

Im currently disabling an application via
setApplicationEnabledSetting(String, int, int)
The application is actually disabling itself.
I would expect upon re-installation of the app, the app would re-enable itself, however this isnt the case.
Is there a particular setting required in the manifest to make this work.
(Ive tried setting enabled=true)
Thanks
Im currently disabling all components apart from a broadcast receiver and am trying to catch the installation process to re-enable all the other components again. Which is nasty to say the least
One way to do this is to listen to package installation broadcasts and take action accordingly.
Listen to Intent.ACTION_PACKAGE_ADDED in your broadcast receiver.
If the newly added package is yours, enable the other components.
Example
Manifest:
<receiver android:name =".MyReceiver">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_ADDED"/>
<data android:scheme="package" />
</intent-filter>
</receiver>
Receiver:
public class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {
final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
final String packageName = intent.getData().getSchemeSpecificPart();
if (replacing && "my.package.name".equals(packageName)) {
// Re-enable the other components
}
}
}
}
Hope this helps.

"Private" intent filter for self app use only

I have created a file explorer and register
<action android:name="android.intent.action.GET_CONTENT" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.OPENABLE" />
But I don't want my internal file explorer is begin shown for user to choose when another app send implicit intent with "Openable" category. How can I do so? Should I just create my own action name?
I don't have the explicit one because I want user to choose other file explorer within my app.
If it's important that only your own app is able to start one of your components, set the exported attribute to "false" for that component in the manifest.
if you asking me - I think that for your situation the best thing is to create your own intent filter (as you sugested in your question), because if you declare your activity to receive a system built in broadcast - it have a meaning. so what's the point using this built in broadcast, if you kind of "breaking his contract" from a system point of view, and want to ignore it in some cases?
if you'll decide to use this built in filter anyway although what I've suggested, the way to achieve what you want is:
register your receiver not in the manifest, but in the onCreate() method of your first launch activity, and unregister him in the onDestroy().
that way your activity won't be registered when none of your activities are foreground - that is close to state which application is close from users point of view.
in case you are not sure how it's done, that's the way:
private BroadcastReceiver mMyCustomReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
registerReceiver(mMyCustomReceiver, IntentFilter.create(YOUR_FILTER_ACTION_COMMAND, YOUR_FILTER_DATA_TYPE));
}
#Override
protected void onDestroy() {
unregisterReceiver(mMyCustomReceiver);
super.onDestroy();
}
I agree with Chris Stratton and Tal Kanel.But instead you can use specific "Data" in your intent filter.Documentation says:
An Intent object that contains neither a URI nor a data type passes
the test only if the filter likewise does not specify any URIs or data
types.
So if an intent has "Openable" category and has not data part that matches your intent filter specific data part,your internal file explorer will be not shown for user.
You could use an 'activity-alias' to make a 'copy' of the activity with android:exported="false" and the private intents?
If you are willing to invoke your activity via an explicit intent (ie, giving the target component name) then you can omit having an intent filter for that activity.

How do I access the user calls to mobile?

I want my application to be activated when the user make a specific call. Is there any way to take information which call is making by user in the same time ( not afterwords ) in order to activate the app at the right time ?
Ok i wrote this code for my case and it works:
public class OutgoingCallReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
if(null == bundle) return;
String phonenumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
if( phonenumber.equals("11111111") ) {
Intent myactivity = new Intent(context, MyKeyboard.class);
myactivity.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(myactivity);
}
}
}
In the Manifest i add this:
<receiver
android:name=".OutgoingCallReceiver"
android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
</intent-filter>
</receiver>
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
I don't really know, but I think that's a really dangerous practice. It all depends on what you intend to do with your app. If it's a recording app, I think you can't even think of developping it, or don't post on the internet about it because it would be illegal in many countries. That's how I see and how I feel your question. About Android there is not 15k places to search, have a look at the android API.
http://developer.android.com/reference/android/provider/CallLog.Calls.html
This, for example, I don't know if it's a real time log, or if it's filled after the call is terminated. But you can search in that direction.

Categories

Resources