I have a custom receiver that handles INSTALL_REFERRER intents when the application is installed. It was called once or twice during testing but now doesn't get called at all. I am using an emulator for testing and have gone through the instructions in this test documentation to broadcast an install intent to the emulator. I have also made sure that I hooked up my Android SDK ADB to the emulator, so it should be receiving the broadcasts. In the terminal, it says that my broadcast succeeded, however when I launch the app from the a fresh install the onReceive is never called.
Here the skeleton of my Receiver:
public class CustomReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
//do stuff
//log stuff
}
}
And here is my manifest:
<receiver
android:name="path.to.CustomReceiver"
android:exported="true">
<intent-filter>
<action android:name="com.android.vending.INSTALL_REFERRER"/>
</intent-filter>
</receiver>
I've tried starting with a new emulator to make sure it wasn't blacklisting the calls, and looked through all the documentation and posts about this that I could find, but nothing seems to work. I appreciate any help.
The docs you refer to are from 2013. More recent docs suggest using an InstallReferrerReceiver, which is specifically designed to handle that intent:
The Google Play com.android.vending.INSTALL_REFERRER Intent is broadcast when an app is installed from the Google Play Store. [InstallReferrerReceiver] listens for that Intent, passing the install referrer data to GTM for Mobile Apps and Google Analytics.
Related
How chat apps (e. g. Messenger) listen to incoming messages even if their activity haven't been started yet since in android 3.1 and later this is not possible:
Manifest:
<service android:name=".ManagerService" android:enabled="true" />
<receiver
android:name=".BootFinishedReceiver"
android:directBootAware="true"
android:enabled="true"
android:exported="false"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
Receiver:
public class BootFinishedReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent serviceIntent = new Intent(context, ManagerService.class);
context.startService(serviceIntent);
}
}
There have to be some way around as chat apps are still working this way.
Thanks for any informations or ideas
Your question is quite open-ended and broad. But to the link that you have pointed about the broadcast receiver when the app is not running.
There is a comment on the same answer that says:
Applications are in a stopped state when they are first installed but are not yet launched and when they are manually stopped by the user (in Manage Applications). That means, the user should launch the app at least once after installation to activate the application, then the app can receive all implicit broadcast from OS as normal.
The app is stopped when it is just installed. As soon as you launch the app for the first time, The application can listen to broadcast receivers and can run background services even when the app is closed.
The chat applications basically implement socket.io that keeps up the communication on both ends. Furthermore, you may implement FCM to get notifications and messages even when the app is killed.
I hope you, understand the concept :).
I'm aware of the fact that the app is uninstalled and re-installed during the course of an app update from the play store.
I have a very crucial service which needs to be running ALWAYS in the background. And this service gets killed during the update process. Is there any way to restart this service without having the user to go manually to the app (without going to the activity)?
I've implemented the following code. But somehow this doesn't work either. (Probably because the app gets uninstalled anyway)
public class AppUpdateReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent)
{
if ("android.intent.action.PACKAGE_REPLACED".equals(intent.getAction()))
// Start service here
}
}
MANIFEST:
<receiver android:name="com.company.services.AppUpdateReceiver">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_REPLACED"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
Other info : minSDK = 14, Target SDK = 20
I'm aware of the fact that the app is uninstalled and re-installed during the course of an app update from the play store
No, it is not. Your process is terminated, though.
I have a very crucial service which needs to be running ALWAYS in the background
A user can stop your service whenever the user wants to, above and beyond the OS terminating your process whenever the OS feels that it is appropriate.
But somehow this doesn't work either
Try to use ACTION_MY_PACKAGE_REPLACED instead and see if that helps.
In XiaoMi 2A, Android Version 4.1, I cann't receive any broadcast after reboot unless I launch my app. XiaoMi disabled boot completed broadcast for apps in default unless users open it.
I have read a lot of posts here:
Broadcast receiver not working in ICS if the app is not started atleast once
http://commonsware.com/blog/2011/07/13/boot-completed-regression-confirmed.html
Cannot receive broadcast in ICS
They all said google just made it happen after Android version 3.0. The truth is with my Galaxy Nexus of Android 4.3, the custom broadcast(not boot completed) can be received even app is not launched before after reboot.
Even with XiaoMi System, broadcast can be received after I open boot completed permission for my app. Can someone tell me why?
Here is the sending Intent:
Intent intent = new Intent();
intent.setAction("com.test.test");
intent.setFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES | intent.getFlags());
context.sendBroadcast(intent);
and the receive is below:
<receiver
android:name="com.test.TestReceiver"
android:exported="true">
<intent-filter>
<action android:name="com.test.test"></action>
</intent-filter>
</receiver>
public class TestReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("com.test.test")) {
Log.e("Chris", "received test action");
}
}
}
In Xiaomi, you can select which all apps can auto start.
Security App > Permissions > Autostart
You can allow autostart for your app here.
I think this will fix your problem
I originally asked this question, about passing parameters through a market link into my app on install.
Everyone seems to be saying to create a BroadcastListener with the intent-filter action of com.android.vending.INSTALL_REFERRER. All the documentation on that seems to imply this is a capability of Google Analytics (the documentation is in v1, but I can only download v2 SDK at this point... so that's what I am using). I can't get these links to pass data through. I have my full manifest and my broadcast listener. I have included Google Analytics just in case that was a requirement.
Google Analytics Reference
Generated link to market from here
Link to my app in the store
Link with parameters in the store
It doesn't work at all. My broadcast listener is never called, nothing gets printed out in the logs. Help!
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.robotsidekick.webbrowser"
android:versionCode="4"
android:versionName="4.0">
<uses-sdk android:minSdkVersion="17"/>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:label="#string/app_name"
android:icon="#drawable/ic_launcher">
<activity
android:name="WebBrowser"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<receiver
android:exported="true"
android:name="com.robotsidekick.webbrowser.InstallReceiver">
<intent-filter>
<action android:name="com.android.vending.INSTALL_REFERRER" />
</intent-filter>
</receiver>
</application>
</manifest>
Broadcast Listener
public class InstallReceiver extends BroadcastReceiver
{
private static final String TAG = "InstallReceiver";
public void onReceive(Context context, Intent intent)
{
Log.e(TAG, "Context: " + context);
Bundle extras = intent.getExtras();
if (extras != null)
{
Log.e(TAG, "Extras:");
for (String keys : extras.keySet())
{
Log.e(TAG, keys + " -> " + extras.get(keys));
}
}
else
{
Log.e(TAG, "Extras are null");
}
}
}
So xbakesx says that it seems to work if his receiver extends com.google.analytics.tracking.android.AnalyticsReceiver.
I think the key is that the intent has permissions for ...AnalyticsReceiver and so no other class that is not extending it can pick up the intent. If you look at their test broadcast https://developers.google.com/analytics/solutions/testing-play-campaigns it does appear specific for that class.
If you change that test broadcast so that your class replaces com.google.analytics.tracking.android.AnalyticsReceiver you can then receive it. The biggest problem is they seemed to have locked down this class in beta 4 or 5. If anyone has a link to beta 3 we could test this, or if xbakex could confirm with playing around with the new jars that would rock!
Update:
BAM! So permissions are not an issue. I created a test project and used the PlayStores alpha testing to test out referrer links, which you can build here: https://developers.google.com/analytics/devguides/collection/android/v2/campaigns.
The cool thing is you don't need any GA jar at all! Checkout my test project here: https://github.com/twotoasters/AnalyticsTest/ This project also shows you how to parse the link to get all of the information that you need.
After many failed attempts i could finally see the passed referral parameters in logcat.
Along the way, i figured out a few things, i am not too sure if i am doing it rite or wrong, but for some reasons, these worked. If someones still stuck, they can get some pointers from my learnings.
A. creating a custom BroadcastReceiver where you can ready the intent. (this will executed, only once you have successfully fired the Install_referrer intent from the ADB for testing). Also make sure, if you need to do a post back of the referrer information to a server, it will have to be on a separate thread.
public class CustomBR extends BroadcastReceiver {
private static final String D_TAG = "BR";
#Override
public void onReceive(Context context, Intent intent) {
Log.d(D_TAG, "CustomReceiver onReceive (context, intent)");
try {
String referrer = intent.getStringExtra("referrer");
// pass the referrer string to another singleton class to post it to server
HandleServerComm.getInstance().postData(referrer);
} catch (Exception e) {
e.printStackTrace();
}
}
}
B. update the androidmanifest.xml file to reflect the custom receiver you have created
<receiver android:exported="true" android:name="com.example.myapp.CustomBR" android:enabled="true">
<intent-filter>
<action android:name="com.android.vending.INSTALL_REFERRER" />
</intent-filter>
</receiver>
C. make sure you have adb installed correctly to test this on local environment. you will also need a device to be connected via USB with remote debugging enabled.
D. run the adb shell command to remotely broadcast a install_referrer on the device and pass it parameters.
The command is
adb shell am broadcast -a com.android.vending.INSTALL_REFERRER -n com.example.myapp/.CustomBR --es "token" "sample_token" --es "source" "banner"
Note that the important parts of this command is com.example.myapp/.CustomBR and --es "token" "sample_token" where --es is the additional parameters that are being sent along with the intent. the first quote after --es is the querystring / parameter name and the second quote is the value. Similarly, if you have to add more than one value, replicate it as shown in the example above.
E. Finally the most important part that kept me frustrated all the while - the app installed on the device itself. Your app should be installed on the device but not running at all. To do this, you will have to "Force Close" the app and then fire the adb shell command to fire up the install_referrer. thats when, you should see the logcat light up with required data.
F. You might also want to uninstall the update on google play store app and restore it to factory settings. at times (not confirmed) the version of google play determines what data is being passed to the app via the install_referrer or if the referrer is called at all.
Hope this helps someone.
Registering a BroadcastReceiver in your app's AndroidManifest.xml with an intent filter is the correct solution to app install referrals whether using Google Analytics or not.
<receiver
android:exported="true"
android:name="com.yourcompany.package.receivers.InstallReceiver">
<intent-filter>
<action android:name="com.android.vending.INSTALL_REFERRER" />
</intent-filter>
</receiver>
If you're already using Google Analytics you simply specify android:name="com.google.android.gms.analytics.CampaignTrackingReceiver" for your receiver and the following service as well. Both are included in the Google Play services client library so there isn't any Java code to write. If you haven't already, you will also have to go through the initial setup instructions for Google Analytics for your App.
<service android:name="com.google.android.gms.analytics.CampaignTrackingService" />
If you're not using Google Analytics then you'll need to define your own BroadcastReceiver in your java code. You will want it to inspect the extras on the received intent when implementing onReceive.
The referrer parameter in the URL that is received by Google Play (the store) is the only parameter passed through to the Android app for the referral so it's very common to encode a few parameters within it. For Google Analytics that means industry standard utm_* parameters, but you can use others. Here's the test adb command I typically use for opening Google Play to install and test the full flow.
adb shell "am start -a android.intent.action.VIEW -d \"https://play.google.com/store/apps/details?id=com.somecompany.package&referrer=utm_source%253Dtest_campaign_source%2526utm_medium%253Dtest_campaign_medium%2526utm_term%253Dtest_campaign_term%2526utm_content%253Dtest_campaign_content%2526utm_campaign%253Dtest_campaign_name\""
Testing Notes:
When testing this flow it's very important to check that the above command resulted in an output where the Intent was logged to your console with the FULL referrer information still attached. It's very easy for the escaping to be incorrect and silently drop the referrer.
Remember that the APK must have been installed by Google Play (the Store) on to the device you're testing on (you can't side-load). Therefore, you usually need to use your Alpha distribution channel in Google Play to test this.
It's important to note that if the device is >= Honeycomb MR1 the INSTALL_REFERRER intent is broadcast after the App is first launched rather than after the app is installed.
You will need to reinstall your app every time you need to test the referrer flow.
Install referrals are tracked when the app is installed from the Android Google Play app, but not the web version of the store.
OK, so not entirely sure this is possible...
But trying to write an application so that I can run some code before any of the following activities are performed.
1) APK is downloaded from web and market launches installer
2) Install button is pressed on android market
Is it possible to intercept and prompt on these events, or has Google locked that stuff down quite tightly?
This isn't an answer per se, but I can't find any commenting tool here. Sorry.
I'm having this issue as well. I would like to be able to detect new application installs. I know it is possible - for example, the app Apps to SD posts a notification when you install a new app that when clicked opens a dialog to move that new app to the sd card.
So far, all I've been able to figure is like this:
manifest.xml:
...
<receiver android:name=".IntentReceiver">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_ADDED" />
<action android:name="android.intent.action.PACKAGE_REMOVED" />
<data android:scheme="package" />
</intent-filter>
</receiver>
...
IntentReciever.java:
public class IntentReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
context.startService(new Intent(context, YourService.class));
}
}
YourService is then created and calls onCreate() then onStartCommand(). However, I haven't been able to debug this or successfully display any notifications from the service class, so I'm not entirely sure this works. I have gotten this to work for other Receivers like android.intent.action.BOOT_COMPLETED.
Using a BroadcastReceiver you can filter the android.intent.action.PACKAGE_ADDED intent. However this will only be after the two actions you describe, not before. And it will not stop or interrupt the installation.
AFAIK there is no way to do anything before or to interrupt the Market. And then we're even talking about another app than the one that's being installed ofcourse.