How to confirm if application has been installed from deeplink / referlink? - android

I'd like to know if there is a way maybe with firebase or appsFLyer etc or natively to know if user came from a deeplink and installed my application is there a way to know the deeplink ?
Basically i'd like an intent passed to me after the user installs the app from the play store (assuming the user got to the play store from a deepLink or some referer link).
Lets imagine the user did not have my automobile app but saw an ad about cars that i had put up. he then clicks that ad and is directed to install my app. after installing my app i'd like the user to see the car they were looking at initially in the ad.

Good example was described in that post
You have to create specific BroadcastReceiver
Add in Manifest:
<receiver android:name="your.package.InstallListener" android:exported="true">
<intent-filter>
<action android:name="com.android.vending.INSTALL_REFERRER" />
</intent-filter>
</receiver>
and create BroadcastReceiver class which will catch deeplink
public class InstallListener extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String rawReferrerString = intent.getStringExtra("referrer");
if (rawReferrerString != null) {
Log.i("MyApp", "Received the following intent " + rawReferrerString);
}
}
}
And add referrer parameter to url using js like this:
var fallbackFunction = function() {
window.location.replace('market://details?id=io.branch.testbed&referrer=specialparam');
};
var addIFrame = function() {
var iframe = document.createElement("iframe");
iframe.style.border = "none";
iframe.style.width = "1px";
iframe.style.height = "1px";
iframe.src = 'your_uri_scheme://';
document.body.appendChild(iframe);
};
addIFrame();
setTimeout(fallbackFunction, 250);
By the way if that method does not work you can try to get specific parameter of phone in js (like vendor, model, etc) and save it in cloud database like firebase. Then after user installed application (PACKAGE_INSTALLED BroadcastReceiver or just first launch) you can check database for last data for his specific parameter and get his deeplink.
If you dont have too much users that will work correctly enough.

Related

Can't get voice commands on Android Auto Media App work

I have an Android App with working Auto capabilities which has been rejected from the store because:
"Your app does not support all of the required voice commands.
For example, your app does not contain an Intent filter for action "android.media.action.MEDIA_PLAY_FROM_SEARCH"."
So i looked to at least make the app respond to "play music on X app" but by looking at the documentation I can't get it to work. I added this to my main activity (which is not the launcher activity, it controls the service via binder)
<intent-filter>
<action android:name="android.media.action.MEDIA_PLAY_FROM_SEARCH" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
which triggers a MediaBrowserServiceCompatwhich is initialized this way:
manifest:
<service
android:name=".Services.RadioService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.media.browse.MediaBrowserService" />
</intent-filter>
</service>
part of the code:
#Override
public void onCreate() {
super.onCreate();
audioManager = (AudioManager) getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
mSession = new MediaSessionCompat(this, "RService");
mSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS | MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS
| MediaSessionCompat.FLAG_HANDLES_QUEUE_COMMANDS);
mSession.setCallback(mCallback);
mSessionConnector = new MediaSessionConnector(mSession);
setSessionToken(mSession.getSessionToken());
setMediaBrowser();
initializeReceiver();
C_F_App.createNotificationChannelPlayer(getApplicationContext());
rNController = new RadioNotificationController(this, mSession, getApplicationContext());
}
final MediaSessionCompat.Callback mCallback =
new MediaSessionCompat.Callback() {
#Override
public void onPlayFromMediaId(String mediaId, Bundle extras) {
playForAuto(mediaId);
}
#Override
public void onPlayFromSearch(String query, Bundle extras) {
super.onPlayFromSearch(query, extras);
Log.d("Test", "Test");
}
#Override
public void onStop() {
playPause();
}
#Override
public void onPlay() {
playPause();
}
#Override
public void onPause() {
playPause();
}
};
public void setMediaBrowser() {
mediaBrowser = new MediaBrowserCompat(getApplicationContext(),
new ComponentName(getApplicationContext(), this.getClass()),
new MediaBrowserCompat.ConnectionCallback() {
#Override
public void onConnected() {
super.onConnected();
}
#Override
public void onConnectionSuspended() {
super.onConnectionSuspended();
}
#Override
public void onConnectionFailed() {
super.onConnectionFailed();
}
}, null);
mediaBrowser.connect();
}
#Override
public long getSupportedPrepareActions() {
return PlaybackStateCompat.ACTION_PREPARE_FROM_MEDIA_ID |
PlaybackStateCompat.ACTION_PLAY_FROM_MEDIA_ID |
PlaybackStateCompat.ACTION_PREPARE_FROM_SEARCH |
PlaybackStateCompat.ACTION_PLAY_FROM_SEARCH;
}
Auto capabilities work fine.
When i try to call this app on Auto from the emulator to play music it just does't do anything, it does not say errors or other stuff, it just closes google speak and then returns to the normal display. The method onPlayFromSearch is never called and it should be the one Auto would call if a voice command is sent.
Can someone help me figure out what i'm doing wrong? Google doc is pretty useless this way, Google UAP doesen't look to have this capability like the old version but looking at the old UAP version i cannot figure out what I'm doing wrong.
PS. The app is not published yet with this functionality
Thanks in advance.
To clear the review process, you’ll only need to get “Play X” (while the app is running in the foreground) working. After adding the intent filter, and if the app handles the search query while its running, I’d kick off another app review.
Otherwise, I believe it’s more of a Google Assistant feature that handles “Play X on Y” when the app is not in the foreground. I don’t have all the details on this, but the assistant may be querying their servers for the app name and package. If it isn’t published yet, it may not work locally.
EDIT
The best way to test your intent filter to clear the app review is to call the intent from adb on the mobile device with:
adb shell am start -a android.media.action.MEDIA_PLAY_FROM_SEARCH
If your app appears in the following media list drawer, the intent filter is setup correctly. You should then see the onPlayFromSearch "Test" log fire when "Play music" is sent while the app is running on Android Auto via the Desktop Head Unit.

Xamarin Android: get one app's state information from another

I have two Xamarin Android apps -- let's call them "Archy" and "Mehitabel".
Archy has some persistent state information (which, let's say for the sake of argument, is in a SQLite DB).
If a certain thing happens to Mehitabel, she needs to know a piece of that state information.
To accomplish this feat, I have Mehitabel send an intent to Archy. Archy has a broadcast receiver that hears it, gathers the necessary state, and fires a different intent back to Mehitabel.
Here's the code from Archy:
[BroadcastReceiver(Enabled = true)]
[IntentFilter(new [] { "com.example.Archy.SendStateToMehitabel"})]
public class StateQueryReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
var msg = new Intent("com.example.Mehitabel.StateFromArchy");
msg.PutExtra("ImportantStateInfo", GetSomeState());
context.SendBroadcast(msg);
}
}
And here's the code from Mehitabel:
private async Task AskArchyForState()
{
var filter = new IntentFilter("com.example.Mehitabel.StateFromArchy");
var csrc = new TaskCompletionSource<bool>();
var rcvr = new ActionBroadcastReceiver((context, intent) =>
{
State = intent.GetStringExtra("ImportantStateInfo");
csrc.TrySetResult(State != null);
});
RegisterReceiver(rcvr, filter);
var msg = new Intent("com.example.Archy.SendStateToMehitabel");
SendBroadcast(msg);
var task = await Task.WhenAny(csrc.Task, Task.Delay(Timeout));
UnregisterReceiver(rcvr);
if (task != csrc.Task)
bomb("Archy has not answered state query after {0}ms", Timeout);
if (!csrc.Task.IsCompletedSuccessfully || csrc.Task.Result == false)
bomb("failed to get all necessary state from Archy");
}
That all works great, provided Archy is actually running (i.e., shown in the "recent" list). If Archy isn't running, Archy's receiver code is never executed and Mehitabel times out.
My hope is I'm missing something simple (like a flag in one of the receiver attributes, or some secret sauce in the com.example.Archy.SendStateToMehitabel intent).
Can you tell me what I'm missing here?
Do I need to be using a completely different approach (like having Mehitabel StartActivityForResult() an activity within Archy, or using a service that starts on boot and runs all the time)?
Based on my research, I think you could open Archy before you need the data in Mehitabel. This is demo about opening an app in code.
Intent launchIntent = PackageManager.GetLaunchIntentForPackage("NewTestApp.NewTestApp");
if (launchIntent != null)
{
StartActivity(launchIntent);
}
Note:NewTestApp.NewTestApp is package name of Archy.

"com.android.vending.INSTALL_REFERRER" fetching referrer parameters on Broadcast has up to 15 seconds delays on some devices

My server creates a link that redirects and passes parameters to google play store;
The sms I receive by my Server;
https://goo.gl/{UNIQUE_ID}
when I click, I actually click on this this url below;
http://www.mycompany.com/env=dev&token=123&id=456
The link above directs me to google play store to my app included parameters;
https://play.google.com/store/apps/details?id=com.mycompany.app&referrer=123,456
Here is the question;(First time installation)
When I install the app opened with the link above, I want to pass those "token", "id" parameters to my app in first time then I will skip login. These parameters creating by server because they are also unique to user.
I have setup the "com.android.vending.INSTALL_REFERRER" and I am able to receive parameters as expected but not consistent on every devices and could face with big delays.
<receiver
android:name=".GooglePlayReceiver"
android:exported="true"
android:permission="android.permission.INSTALL_PACKAGES">
<intent-filter>
<action android:name="com.android.vending.INSTALL_REFERRER" />
</intent-filter>
</receiver>
My GooglePlayReceiver Broadcastreceiver is;
public class GooglePlayReceiver extends BroadcastReceiver {
Context mContext;
String purchaseId = null;
public GooglePlayReceiver() {
}
#Override
public void onReceive(Context context, Intent intent) {
try {
mContext = context;
Bundle extras = intent.getExtras();
String verificationCode = null;
String phoneNumber = null;
if (extras != null) {
String code = extras.getString("referrer");
String[] strArr = code != null ? code.split(",") : new String[0];
token = strArr[0];
id = strArr[1];
}
} catch (Exception ex) {
}
}}
This flow has big delays on some devices. For ex, Google Pixel 2 fetches the parameters immediately without delay, Samsung Galaxy S7 has 5-10 seconds delay.
How to solve this?
Because the INSTALL_REFERRER is sent as a broadcast (documentation) it uses the publish subscribe model. There is no guarantee about timing.
Because of this you shouldn't design your app startup flow to rely on receiving the broadcast within a certain length of time. Android is open source, and changes made my different phone manufacturers will cause different promptness in the delivery of broadcasts.
I'd have a different design for your app:
take the user always to the normal setup flow
if the broadcast arrives later, allow the user to skip login

Android notification using Firebase

I'm developing a android application and different users will be use it.
I need to give some notification to a user when another user do some activity. I planed to do it with firebase cloud messaging(FCM). but i don't know how to detect the relevant device.
Step 1: Register with Firebase Developers Console
In order to use FCM, you need to login to console. You should be given a choice on the right-hand side as to whether to create a new project or import an existing Google app into Firebase.
Click on Add App and then copy the google-services.json file that will get downloaded into yourapp/ dir. This file includes the project information and API keys needed to connect to Firebase. Make sure to preserve the filename, since it will be used in the next step.
Finally, add the Google services to your root build.gradle file's classpath:
buildscript {
dependencies {
// Add this line
classpath 'com.google.gms:google-services:3.0.0'
}
}
Add to your existing app/build.gradle at the end of the file:
apply plugin: 'com.google.gms.google-services'
Step 2 - Download Google Play Services
First, let's download and setup the Google Play Services SDK. Open Tools->Android->SDK Manager and check whether or not you have already downloaded Google Play Services under the Extras section. Make sure to update to the latest version to ensure the Firebase package is available.
Step 3 - Add Google Repository
Also open Tools->Android->SDK Manager and click on the SDK Tools tab. Make sure that under Support Repository you have installed the Google Repository. If you forget this step, you are not likely to be able to include the Firebase messaging library in the next step.
Step 4 - Update to SDK Tools
Also make sure to upgrade to SDK Tools 25.2.2. You may have Firebase authentication issues with lower SDK Tools version.
Step 6 - Import Firebase Messaging Library
Add the following to your Gradle file:
dependencies {
compile 'com.google.firebase:firebase-messaging:9.4.0'
}
Step 7 - Implement a Registration Intent Service
You will want to implement an Intent Service, which will execute as a background thread instead of being tied to the lifecycle of an Activity. In this way, you can ensure that push notifications can be received by your app if a user navigates away from the activity while this registration process is occuring.
First, you will need to create a RegistrationIntentService class and make sure it is declared in your AndroidManifest.xml file and within the application tag:
<service android:name=".RegistrationIntentService" android:exported="false"/>
Inside this class, you will need to request an instance ID from Google that will be a way to uniquely identify the device and app. Assuming this request is successful, a token that can be used to send notifications to the app should be generated too.
public class RegistrationIntentService extends IntentService {
// abbreviated tag name
private static final String TAG = "RegIntentService";
public RegistrationIntentService() {
super(TAG);
}
#Override
protected void onHandleIntent(Intent intent) {
// Make a call to Instance API
FirebaseInstanceId instanceID = FirebaseInstanceId.getInstance();
String senderId = getResources().getString(R.string.gcm_defaultSenderId);
try {
// request token that will be used by the server to send push notifications
String token = instanceID.getToken();
Log.d(TAG, "FCM Registration Token: " + token);
// pass along this data
sendRegistrationToServer(token);
} catch (IOException e) {
e.printStackTrace();
}
}
private void sendRegistrationToServer(String token) {
// Add custom implementation, as needed.
}
}
You will want to record whether the token was sent to the server and may wish to store the token in your Shared Preferences:
public static final String SENT_TOKEN_TO_SERVER = "sentTokenToServer";
public static final String FCM_TOKEN = "FCMToken";
#Override
protected void onHandleIntent(Intent intent) {
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
// Fetch token here
try {
// save token
sharedPreferences.edit().putString(FCM_TOKEN, token).apply();
// pass along this data
sendRegistrationToServer(token);
} catch (IOException e) {
Log.d(TAG, "Failed to complete token refresh", e);
// If an exception happens while fetching the new token or updating our registration data
// on a third-party server, this ensures that we'll attempt the update at a later time.
sharedPreferences.edit().putBoolean(SENT_TOKEN_TO_SERVER, false).apply();
}
}
private void sendRegistrationToServer(String token) {
// send network request
// if registration sent was successful, store a boolean that indicates whether the generated token has been sent to server
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
sharedPreferences.edit().putBoolean(SENT_TOKEN_TO_SERVER, true).apply();
}
You will want to make sure to dispatch this registration intent service when starting up your main activity. There is a Google Play Services check that may require your activity to be launched in order to display a dialog error message, which is why it is being initiated in the activity instead of application.
public class MyActivity extends AppCompatActivity {
/**
* Check the device to make sure it has the Google Play Services APK. If
* it doesn't, display a dialog that allows users to download the APK from
* the Google Play Store or enable it in the device's system settings.
*/
private boolean checkPlayServices() {
GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance();
int resultCode = apiAvailability.isGooglePlayServicesAvailable(this);
if (resultCode != ConnectionResult.SUCCESS) {
if (apiAvailability.isUserResolvableError(resultCode)) {
apiAvailability.getErrorDialog(this, resultCode, PLAY_SERVICES_RESOLUTION_REQUEST)
.show();
} else {
Log.i(TAG, "This device is not supported.");
finish();
}
return false;
}
return true;
}
#Override
protected void onCreate() {
if(checkPlayServices()) {
Intent intent = new Intent(this, RegistrationIntentService.class);
startService(intent);
}
}
}
Step 8 - Create a InstanceID ListenerService
According to this Google official documentation, the instance ID server issues callbacks periodically (i.e. 6 months) to request apps to refresh their tokens. To support this possibility, we need to extend from InstanceIDListenerService to handle token refresh changes. We should create a file called MyInstanceIDListenerService.java that will override this base method and launch an intent service for RegistrationIntentService to fetch the token:
public class MyInstanceIDListenerService extends FirebaseInstanceIdService {
#Override
public void onTokenRefresh() {
// Fetch updated Instance ID token and notify of changes
Intent intent = new Intent(this, RegistrationIntentService.class);
startService(intent);
}
}
You also need to add the service to your AndroidManifest.xml file within the application tag:
<service
android:name="com.example.MyInstanceIDListenerService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>
Step 9 - Listening for push notifications
Let's define FCMMessageHandler.java that extends from FirebaseMessagingService that will process the message received:
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
import android.app.NotificationManager;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.NotificationCompat;
public class FCMMessageHandler extends FirebaseMessagingService {
public static final int MESSAGE_NOTIFICATION_ID = 435345;
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Map<String, String> data = remoteMessage.getData();
String from = remoteMessage.getFrom();
Notification notification = remoteMessage.getNotification();
createNotification(notification);
}
// Creates notification based on title and body received
private void createNotification(Notification notification) {
Context context = getBaseContext();
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context)
.setSmallIcon(R.mipmap.ic_launcher).setContentTitle(notification.getTitle())
.setContentText(notification.getBody());
NotificationManager mNotificationManager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(MESSAGE_NOTIFICATION_ID, mBuilder.build());
}
}
We need to register the receiver class with FCM in the AndroidManifest.xml tagging the type of request (category) of the push:
<application
...>
<!-- ... -->
<activity
...>
</activity>
<service
android:name=".FCMMessageHandler"
android:exported="false" >
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
</application>
</manifest>

Properly tracking install referrals on Play Store

I have a simple task: I want to track the referral id of an app install and pass it to backend.
What I did: I created a link with an extra parameter referrer and appended it to the invite link. When it is opened, the javascript detects if the browser is an Android mobile browser and then prepares an intent and issues a redirect to that intent. While preparing the intent, referrer field is extracted from the url and appended to the intent like this:
intent://scan/#Intent;scheme=com.example.android;package=com.example.android&referrer=4;end
And here is my code for BroadCastReceiver :
public class InstallReferrerReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
TinyDB tinyDB = new TinyDB(context);
String referrer = intent.getStringExtra("referrer");
tinyDB.putString(AppConstants.REFERRAL_ID, referrer);
tinyDB.putBoolean(AppConstants.REFERRAL_SENT, false);
}
}
So, what I expect to get here as the value of referrer is 4 based on the above intent. But the value that I am getting is this String utm_source=google-play&utm_medium=organic
What am I doing wrong and how can I fix it to get the correct value for referrer field?
Edit
I don't have any issues in creating the url or extracting values from referrer field once the app is installed.
Once the invite link is clicked through any button click or opened directly in the mobile browser, I use the above to "either open the app if it is already installed or open the app's page on Play Store app for users to install it".
The issue is, how should I pass the value of referrer field from the invite link to the Play Store app through the above intent so that the Play Store receives this value and passes it to the app when it is installed.
You need to test it properly, I am posting mine use case, hope it will solve your problem :)
Refferal URL -
https://play.google.com/store/apps/details?id=com.mypackage&referrer=utm_source%3Dmobisoc%26utm_content%3D{transaction_id}%26utm_campaign%3D1
Code to receive refferal -
public static final String KEY_UTM_SOURCE = "utm_source";
public static final String KEY_UTM_CONTENT = "utm_content";
public static final String KEY_UTM_CAMPAIGN = "utm_campaign";
public void onReceive(Context context, Intent intent) {
Utils.log("Referral Received");
try {
String referrer = intent.getStringExtra("referrer");
if (referrer != null && !referrer.equals("")) {
Utils.log("Referral Received - " + referrer);
String[] referrerParts = referrer.split("&");
String utmSource = getData(KEY_UTM_SOURCE, referrerParts);
String utmContent = getData(KEY_UTM_CONTENT, referrerParts);
String utmCampaign = getData(KEY_UTM_CAMPAIGN, referrerParts);
if (utmSource != null && utmSource.equals("mobisoc")) {
sendLogToMobisocServer(context, utmContent);
} else if (utmSource != null && utmSource.equals("app_share")) {
RawStorageProvider.getInstance(context).dumpDataToStorage(RaghuKakaConstants.REFFERAL_FOR, utmContent);
}
updateRKServerForReferral(context, utmSource, utmCampaign, utmContent);
}
} catch (Exception e) {
e.printStackTrace();
}
}
private String getData(String key, String[] allData) {
for (String selected : allData)
if (selected.contains(key)) {
return selected.split("=")[1];
}
return "";
}
Now the most important part testing. You can test the referral locally. Just you need to attach your phone, open the shell prompt by using adb shell. And broadcast the referral data.
Here are the command sequence example -
C:\Users\Neo\Desktop>adb shell
$ am broadcast -a com.android.vending.INSTALL_REFERRER -n com.mypackage/<className of your ReferralReceiver with package> --es "referrer" "utm_source%3Dmobisoc%26utm_content%3D{transaction_id}%26utm_campaign%3D1"
Additional -
https://play.google.com/store/apps/details?id=com.mypackage&referrer=utm_source%3Dmobisoc%26utm_content%3D{transaction_id}%26utm_campaign%3D1
Just see my link. If user will go to the playstore via that link, and install the app. Then first time when the app will launch, your onReceive method will be fired automatically, and you will get all the data after referrer=.
Broadcast -
$ am broadcast -a com.android.vending.INSTALL_REFERRER -n com.mypackage/<className of your ReferralReceiver with package> --es "referrer" "utm_source%3Dmobisoc%26utm_content%3D{transaction_id}%26utm_campaign%3D1"
For testing it you no need to publish your app on playstore, Just put a debug point on first point of onReceive, launch in debug mode, and fire the command sequences I have posted, you will get all the data after "referrer" tag. So by this you can decide what data you need to add while creating the referrer link.
Let me know in case of more clarification you need :)
It is better and more reliable to track referrer via Firebase Dynamic Link.
Below this how it work.
https://domain/?link=your_deep_link&apn=package_name[&amv=minimum_version][&ad=1][&al=android_link][&afl=fallback_link]
Here's the example of link after fill in the parameters.
https://example.app.goo.gl/?link=https://www.example.com/someresource&apn=com.example.android&amv=3&al=exampleapp://someresource&ibi=com.example.ios&isi=1234567&ius=exampleapp
Of course, you can shorten the link to something like https://example.app.goo.gl/abcde directly at Firebase console. It will take only few minutes to setup the Dynamic Link.
Then in the Android app on your main Activity you can call AppInvite.AppInviteApi.getInvitation(mGoogleApiClient, this, false) to retrieve link information.
More information can be found here https://firebase.google.com/docs/dynamic-links/
I have used utm tagging
you can see full source at https://github.com/dheeraj9198/Utm-Test
I am providing the basic code
public class CustomCampaignTrackingReceiver extends BroadcastReceiver {
private static final String TAG = CustomCampaignTrackingReceiver.class.getSimpleName();
private static final Logger LOGGER = LoggerFactory.getLogger(TAG);
private static final Marker MARKER = MarkerFactory.getMarker(TAG);
#Override
public void onReceive(Context context,final Intent intentx) {
LOGGER.info(MARKER, "on Receive called");
ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.execute(new Runnable() {
#Override
public void run() {
try {
for (String key : intentx.getExtras().keySet()) {
try {
LOGGER.info(MARKER, key + " => " + String.valueOf(intentx.getExtras().get(key)));
} catch (Exception e) {
LOGGER.error(MARKER, "caught exception in on key retrieval ", e);
}
}
} catch (Exception e) {
LOGGER.error(MARKER, "caught exception in key loop ", e);
}
}
});
executorService.shutdown();
}
}
--------------------------Manifest---------------------------------------
<receiver
android:name="com.google.android.gms.analytics.CampaignTrackingReceiver"
android:exported="true" >
<intent-filter>
<action android:name="com.android.vending.INSTALL_REFERRER" />
</intent-filter>
</receiver>
<receiver
android:name=".receivers.CustomCampaignTrackingReceiver"
android:exported="true" >
<intent-filter>
<action android:name="com.android.vending.INSTALL_REFERRER" />
</intent-filter>
</receiver>

Categories

Resources