I try to receive an event everytime a new shortcut on the Homescreen/Luncher was created. After my app receive the event I like to modify the shortcut. My current configuration is listed below, but I never receive an event.
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
<uses-permission android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT" />
<application>
<receiver
android:name=".InstallShortcutReceiver"
android:permission="com.android.launcher.permission.INSTALL_SHORTCUT">
<intent-filter>
<action android:name="com.android.launcher.action.INSTALL_SHORTCUT" />
</intent-filter>
</receiver>
</application>
Is my idea possible ?
Best Regards,
André
What happens if you remove the permission line from the receiver? The permission you specify in a receiver like that is the permission necessary to call it, not for it to receive broadcasts.
I found it. When I shortcut is created using drap and drop from the menu no INSTALL_SHORTCUT event is published.
Related
So I have 2 apps - A and B.
In A i have a BroadcastReceiver. In the receiver tag (manifest file) I specify an android:permission string (let's say com.example.app.SEND). Now B cannot send broadcasts to A anymore. Makes sense!
So what do I have to do in order for B to send broadcasts to A ? In B's manifest, I specified uses-permission tag with android:name set to the same string (com.example.app.SEND) as the receiver's android:permission but still the broadcasts won't go from B to A.
What am I doing wrong ? Or is there something else that needs to be done ?
-- Update --
Here's my app A's receiver tag:
<receiver
android:name="com.example.app.MyReceiver"
android:enabled="true"
android:exported="true"
android:permission="com.example.BReceiver.SEND" >
<intent-filter>
<action android:name="com.example.BReceiver" />
</intent-filter>
</receiver>
And here's the uses-permission tag from my B's manifest:
<uses-permission android:name="com.pycitup.BReceiver.SEND" />
So I'd to set a custom permission for the same string like this in B's manifest:
<permission android:name="com.pycitup.BReceiver.SEND" />
Was quite straight-forward and simple. Just required a bit of reading across the web.
From B create an intent and set the action to your broadcast receivers name.
Intent myintentB=new Intent();
myintentB.setAction("com.example.app.SEND");
sendBroadcast(myintentB);
This should technically hit your receiver.
I have some receivers declared in my AndroidManifest :
<!-- no warning -->
<receiver
android:name=".receivers.TriggerMonitoringBootReceiver"
android:enabled="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<!-- no warning -->
<receiver
android:name=".receivers.ScanResultsReceiver"
android:enabled="false">
<intent-filter>
<action android:name="android.net.wifi.SCAN_RESULTS" />
</intent-filter>
</receiver>
<!-- warning : Exported receiver does not require permission-->
<receiver
android:name=".receivers.BatteryMonitoringReceiver"
android:enabled="false">
<intent-filter>
<action android:name="#string/intent_action_setup_alarm" />
<action android:name="#string/intent_action_cancel_alarm" />
<action android:name="#string/intent_action_monitor" />
</intent-filter>
</receiver>
The first one is meant to receive a BOOT_COMPLETED action. The second is meant to receive android.net.wifi.SCAN_RESULTS. The third one is meant to receive some actions I broadcast (intent_action_monitor) and some actions broadcasted by the AlarmManager (intent_action_setup_alarm etc).
Two questions:
Why don't I get the warning on all receivers?
What permissions do I need to set for receivers meant to receive from system services to correct the warning (I understand what it is about and I don't want anyone to use my receivers anyway) ? Will exported="false" do for boot receivers, wifi receivers, alarm receivers etc?
I thought of using a custom permission with android:protectionLevel="signatureOrSystem" but the docs advise against both this protection level and custom permissions. So how I should handle this warning ?
Links to the docs and/or some code will be much appreciated.
Why don't I get the warning on all receivers ?
Because the first two are clearly designed to be broadcast by Android. The last one is unknown, partly because you did not supply the string resource values, and possibly because they are your own unique action strings.
What permissions do I need to set for receivers meant to receive from system services to correct the warning
The correct solution is to delete the <intent-filter>. If you are broadcasting these Intents, or if you are wrapping an Intent in a getBroadcast() PendingIntent, you do not need action strings. Use the Intent constructor that takes the Java class object as the second parameter, and use that:
new Intent(this, BatteryMonitoringReceiver.class)
You are welcome to still attach an action string to that Intent, if you want, but you can dump the <intent-filter> (routing will be based on the supplied component, in this case the Java class).
Only use an <intent-filter> when you are expecting the OS or third-party apps to initiate the Intent themselves (executing a PendingIntent that you created does not count).
The warning "Exported receiver does not require permission" means, You have an intent-filter with some action (which means by default you have android:exported="true" set and it can now receive broadcasts from ANY broadcasters outside of your application) Since it can receive broadcasts from ANY broadcasters outside of your application, it warns you by saying "Hey, are you sure ANY broadcaster can invoke you? In my opinion, it is better if you allow only those broadcasters to invoke you that has the permission you have set for this receiver through android:permission"
You can remove this warning by adding android:exported="false" to the receiver tag
If you do want to export your receiver to other processes, you can add your own permission definition in your android-manifest file for avoiding this warning, like
<permission
android:name="com.yourpage.permission.YOUR_PERMISSION"
android:protectionLevel="normal" />
<uses-permission
android:name="com.yourpage.permission.YOUR_PERMISSION" />
<receiver <!-- warning : Exported receiver does not require permission-->
android:name=".receivers.BatteryMonitoringReceiver"
android:permission="com.yourpage.permission.YOUR_PERMISSION"
android:enabled="false" >
<intent-filter>
<action android:name="#string/intent_action_setup_alarm" />
<action android:name="#string/intent_action_cancel_alarm" />
<action android:name="#string/intent_action_monitor" />
</intent-filter>
</receiver>
for more information, you can refer to http://developer.android.com/training/articles/security-tips.html
If, like me, you are here because your app built with a previous SDK version stopped working with more recent versions and you would like to fix it with minimal change, just add
android:exported=false
to the receiver tag in the manifest file. The solution by CommonsWare is obviously the one to go with for the long term but this fixes the issue temporarily if you are using custom intents and don't mean to export them.
Going by Lubo's way, you would need to export this custom permission, which would prompt the user before installation. That means the descriptive text for the permission needs to be well written so you don't end up scaring the user into changing his mind about installing the app. Also, it would need to be translated into all your target languages.
To hide this warning, add tools:ignore="ExportedReceiver" to the receiver:
<receiver
android:name=".MyReceiverIndentedForOtherAppsWithoutPermissions"
tools:ignore="ExportedReceiver">
<intent-filter>
<action android:name="com.my.app.CUSTOM_ACTION" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
I read loast of tutorials about how to make an app start at system boot (Link, Link...).
My receiver looks like this, the rest like described in the tutorials:
<receiver android:enabled="true" android:name=".BootUpReceiver"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
But my app just won't start... any ideas?
Too stuipid!
You need to add the full path to the receiver class:
<receiver android:enabled="true" android:name="com.mypackage.whatever.BootUpReceiver"
My receiver looks like this, the rest like described in the tutorials
Your <receiver> element is incorrect. You are requiring that the sender of the broadcast hold the RECEIVE_BOOT_COMPLETED permission, which may or may not be true. Please remove the android:permission attribute. If needed, add RECEIVE_BOOT_COMPLETED as a <uses-permission> element, to say that you wish to hold that permission.
I am confused about the a concept here. I read on many tutorials that in order to get notified when device has booted (say for purpose of re-scheduling an alarm), you need to have a boot_completed broadcast receiver.
However the confusing part is that no where I see a method like "register(boradcast receiver)". People just have the broadcast receiver class and they have it in manifest. but dont you need some sort of registration process? How will the system know that there is an APP x who has a broadcast receiver y listening for boot events unless explicitly told through registering
Sort of like you create click listener, but you need to register/add it to the button to so it gets called upon clicked.
Can someone clear the confusion for me?
Thank you
Thanks
People just have the broadcast receiver class and they have it in manifest. but dont you need some sort of registration process?
The <receiver> element in the manifest has the <intent-filter> child element, documenting the Intent structure it wishes to receive:
<?xml version="1.0" encoding="utf-8"?>
<manifest android:versionCode="1"
android:versionName="1.0"
package="com.commonsware.android.sysevents.boot"
xmlns:android="http://schemas.android.com/apk/res/android">
<uses-sdk android:minSdkVersion="3"
android:targetSdkVersion="6" />
<supports-screens android:largeScreens="false"
android:normalScreens="true"
android:smallScreens="false" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application android:icon="#drawable/cw"
android:label="#string/app_name">
<receiver android:name=".OnBootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
</manifest>
Here, we are registering a BroadcastReceiver, named OnBootReceiver, to receive BOOT_COMPLETED broadcasts.
How will the system know that there is an APP x who has a broadcast receiver y listening for boot events unless explicitly told through registering
Android is "explicitly told through registering". It just so happens that the "registering" is done via the manifest, not via Java code in the app.
The short answer:
You can either dynamically register an instance of this class with Context.registerReceiver() or statically publish an implementation through the tag in your AndroidManifest.xml
I'm trying to test the C2DM framework. I got the confirmation email a couple of days ago and then tryied to create a client that could register. For that purpose, I created a simple client following the steps described in this tutorial: http://code.google.com/intl/es-419/android/c2dm/index.html.
The Android manifest file contains among other things this code:
<permission android:name="com.bilthon.ufrj.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="com.bilthon.ufrj.permission.C2D_MESSAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.INTERNET"/>
<receiver android:name=".C2DMReceiver" android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.bilthon.ufrj" />
</intent-filter>
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="com.bilthon.ufrj" />
</intent-filter>
</receiver>
And then, the main activity launched when the program starts has the following code:
Intent registrationIntent = new Intent("com.google.android.c2dm.intent.REGISTER");
registrationIntent.putExtra("app", PendingIntent.getBroadcast(this, 0, new Intent(), 0)); // boilerplate
registrationIntent.putExtra("sender","mytestemail#gmail.com");
Log.d("WelcomeScreen","mytestemail#gmail.com");
startService(registrationIntent);
I also registered a google account on the AVD running my client, as they said it was required. But the problem is that I cannot get the broadcast receiver to "wake up". I don't know what could be wrong. By analysing the logs, I can see that the registration intent is created and apparently used correctly, but the receiver code just never is executed, what could be wrong?
Thanks in advance
Nelson
Well.. just sorted it out, the problem was with the declaration of the receiver. The tags for the receiver should go inside the application tag, just as demonstrated here: http://developer.android.com/guide/topics/manifest/manifest-intro.html
Here's an example of a well formated Manifest for a C2DM application. Thanks to Mark Murphy for posting the link at the android-c2dm group.
And sorry for the silly mistake.
Nelson
I just got this working myself after wrestling with it for some time.
In the manifest, you have the line
<receiver android:name=".C2DMReceiver" android:permission="com.google.android.c2dm.permission.SEND">
Which means you need a class called C2DMReceiver that extends C2DMBaseReceiver in the c2dm package. To get implement this, I copied both the c2dm package and C2DMReceiver.java file from the chrometophone-android example over to my project and was able to get a registration id from the C2DM server as intended.
I had the same problem. My solution was moving all of the permissions in my manifest above the application tag.
Things you can check:
1 I noticed is that you are declaring a C2DM permission but don't use it in your application like so:
<uses-permission android:name="com.bilthon.ufrj.permission.C2D_MESSAGE" />
2 If you have a look at the c2dm library you will see that the helper C2DMessaging's register method creates the intent with an additional call to setPackage.
registrationIntent.setPackage("com.google.android.gsf");