We're planning to use Google Analytics to track ad click-through referrals, through the Android Market, to our application.
According to the Google Documentation the referrer tag comes through via an intent, and is automatically recorded by the Google Analytics library.
That's great, but we need to extract that referral tag for our own internal analytics. The documentation is shy on details about how to grab it out of the initial launch intent, and instructions on how to simulate this before going live.
Does anyone have experience with this?
I went ahead and published a dead pixel finder app to play with snooping on the intent. For some reason, when I registered two different broadcast receivers (ie com.google.android.apps.analytics.AnalyticsReceiver and my own), I never received it on my own.
So instead, I registered only my own receiver, process the information, and pass it along to Google Analytics. Don't know how kosher this is, but it works. Code follows.
public class ZSGoogleInterceptor extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Bundle extras = intent.getExtras();
String referrerString = extras.getString("referrer");
// Next line uses my helper function to parse a query (eg "a=b&c=d") into key-value pairs
HashMap<String, String> getParams = Utility.getHashMapFromQuery(referrerString);
String source = getParams.get("utm_campaign");
if (source != null) {
SharedPreferences preferences = context.getSharedPreferences("my_prefs", Context.MODE_PRIVATE);
Editor preferencesEditor = preferences.edit();
preferencesEditor.putString("ga_campaign", source);
preferencesEditor.commit();
}
// Pass along to google
AnalyticsReceiver receiver = new AnalyticsReceiver();
receiver.onReceive(context, intent);
}
}
Then, when your application is actually launched, you can pull the value back out of the shared preferences and pass it along with user signup or whatever. I used the campaign tag for my purposes, but you can grab any parameters you want out of the referrer string created with this tool.
#DougW 's answer updated for Analytics SDK 4
https://developers.google.com/analytics/devguides/collection/android/v4/campaigns
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import com.google.android.gms.analytics.CampaignTrackingReceiver;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* Created by dave on 15-05-05.
*/
public class ReferrerReceiver extends BroadcastReceiver {
public static final String REFERRER = "REF";
public static final String UTM_CAMPAIGN = "utm_campaign";
public static final String UTM_SOURCE = "utm_source";
public static final String UTM_MEDIUM = "utm_medium";
public static final String UTM_TERM = "utm_term";
public static final String UTM_CONTENT = "utm_content";
private final String[] sources = {
UTM_CAMPAIGN, UTM_SOURCE, UTM_MEDIUM, UTM_TERM, UTM_CONTENT
};
#Override
public void onReceive(Context context, Intent intent) {
Bundle extras = intent.getExtras();
String referrerString = extras.getString("referrer");
try {
Map<String, String> getParams = getHashMapFromQuery(referrerString);
SharedPreferences preferences = context
.getSharedPreferences(REFERRER, Context.MODE_PRIVATE);
SharedPreferences.Editor preferencesEditor = preferences.edit();
for (String sourceType : sources) {
String source = getParams.get(sourceType);
if (source != null) {
preferencesEditor.putString(sourceType, source);
}
}
preferencesEditor.commit();
} catch (UnsupportedEncodingException e) {
Log.e("Referrer Error", e.getMessage());
} finally {
// Pass along to google
CampaignTrackingReceiver receiver = new CampaignTrackingReceiver();
receiver.onReceive(context, intent);
}
}
public static Map<String, String> getHashMapFromQuery(String query)
throws UnsupportedEncodingException {
Map<String, String> query_pairs = new LinkedHashMap<String, String>();
String[] pairs = query.split("&");
for (String pair : pairs) {
int idx = pair.indexOf("=");
query_pairs.put(URLDecoder.decode(pair.substring(0, idx), "UTF-8"),
URLDecoder.decode(pair.substring(idx + 1), "UTF-8"));
}
return query_pairs;
}
}
In you manifest file:
<service android:name="com.google.android.gms.analytics.CampaignTrackingService" />
<receiver android:name="com.google.android.gms.analytics.CampaignTrackingReceiver" />
<!-- Make sure this points to the location of Referrer Receiver in your package -->
<receiver android:name=".ReferrerReceiver" android:exported="true">
<intent-filter>
<action android:name="com.android.vending.INSTALL_REFERRER" />
</intent-filter>
</receiver>
Check at:
Get referrer after installing app from Android Market
for the solutions.
Tobia
Related
I'm currently working on GCM notifications, especially on silent push notification. For the moment, I receive the silent notification, even when the app is closed (which is the aim of my notification). The problem is the code I am trying to execute when receiving this silent push notification :
private void sendPingNotification() {
mWebServiceCoordinator = new WebServiceCoordinator(UserSingleton.getContext(), this);
mWebServiceCoordinator.fetchSessionConnectionData(
UserSingleton.getInstance().getLogin(),
UserSingleton.getInstance().getPassword(),
UserSingleton.getInstance().getDeviceId(),
UserSingleton.getInstance().getDeviceType(),
UserSingleton.getInstance().getAvailability());
}
As you can see, I want to send the UserSingleton's login, password, etc... to my server.
First, I create a new WebServiceCoordinator, which takes the Context of UserSingleton in parameter. And this is where there is a problem : as the application is totally closed, there is not any Context !
Here is the function trying to get the Context in my UserSingleton :
public static Context getContext() {
if (context == null) {
if (MainActivity.isRunning) {
context = MainActivity.getContext();
} else {
Log.e(LOG_TAG, "Unable to get the context");
}
}
return context;
}
This function is perfectly working when the application is running. But as the application is closed and nothing is running, even not MainActivity, the value of context returned by the function is still null
Thus, the next part of my sendPingNotification() doesn't work...
I'm pretty sure there is no way to get a context when an application isn't running (it's logical), but how can I still use my UserSingleton methods ? Because they need a Context to work, for exemple, the getSharedValue() method :
public String getSharedValue(String key, String defaultValue) {
final SharedPreferences data_r = UserSingleton.getContext().getSharedPreferences(SHARED_KEY, Context.MODE_PRIVATE);
return data_r.getString(key, defaultValue);
}
Any ideas ? Thanks
------ EDIT ------
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
public class MyGcmListenerService extends GcmListenerService implements WebServiceCoordinator.Listener {
private static final String TAG = "MyGcmListenerService";
private WebServiceCoordinator mWebServiceCoordinator;
/**
* Called when message is received.
*
* #param from SenderID of the sender.
* #param data Data bundle containing message data as key/value pairs.
* For Set of keys use data.keySet().
*/
#Override
public void onMessageReceived(String from, Bundle data) {
String type = data.getString("type");
String title = data.getString("title");
String message = data.getString("message");
Log.d(TAG, "Notification from " + from + " : (" + type + ")" + " " + message);
if (type.equals("appointment_details")) {
String nom = data.getString("nom");
String prenom = data.getString("prenom");
String mail = data.getString("mail");
String telephone = data.getString("telephone");
String state = data.getString("state");
Integer stateId = Integer.parseInt(data.getString("stateId"));
String date = data.getString("date");
String token = data.getString("token");
String length = data.getString("length");
sendDetailsRendezvousNotification(title, message, nom, prenom, mail, telephone, state, stateId, date, token, length);
}
else if (type.equals("appointment"))
sendNormalNotification(title, message);
else if (type.equals("newCall"))
sendNewCallNotification();
else if (type.equals("ping"))
sendPingNotification();
else if (type.equals("normal"))
sendNormalNotification(title, message);
}
private void sendPingNotification() {
mWebServiceCoordinator = new WebServiceCoordinator(UserSingleton.getContext(), this);
mWebServiceCoordinator.fetchSessionConnectionData(UserSingleton.getInstance().getLogin(),
UserSingleton.getInstance().getPassword(),
UserSingleton.getInstance().getDeviceId(),
UserSingleton.getInstance().getDeviceType(),
UserSingleton.getInstance().getAvailability());
}
}
Ok im pretty sure you can use getApplicationContext to get the context inside a gcm service
mWebServiceCoordinator = new WebServiceCoordinator(getApplicationContext(), this);
So I edited my sendPingNotification() method as following :
private void sendPingNotification() {
mWebServiceCoordinator = new WebServiceCoordinator(getApplicationContext(), this);
UserSingleton.setContext(getApplicationContext());
mWebServiceCoordinator.fetchSessionConnectionData(UserSingleton.getInstance().getLogin(),
UserSingleton.getInstance().getPassword(),
UserSingleton.getInstance().getDeviceId(),
UserSingleton.getInstance().getDeviceType(),
UserSingleton.getInstance().getAvailability());
}
I added a setContext() method in UserSingleton, so that I can set the context of my UserSingleton as getApplicationContext(). The context isn't null anymore and getContext() returns a valid Context. Everything is working ! Thanks to you two.
I have a basic countdown app that counts down from 10 secs when button is clicked. What would be the simplest method to have the timer start when contact is made with a specific NFC tag? (NTAG203)
I've read several NFC tutorials and the only one I've been able to get to work has been a simple tag reader. If I wanted to have a specific NFC tag trigger a simple timer app just like a button would, how would I go about doing so? Would it be best to try to read the ID or just interpret plain text as an identifier?
Thanks (Using Android Studio)
NFC app Main Activity (Code taken from this tutorial: http://shaikhhamadali.blogspot.com/2013/10/near-field-communication-nfc-android.html
package com.example.nfctest2.nfctest2app;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentFilter.MalformedMimeTypeException;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.Ndef;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity {
public static final String MIMETYPE_TEXT_PLAIN = "text/plain";
public static final String TAG = "NfcTut";
private TextView tV_ReadNFC;
private NfcAdapter nfcAdapt;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//initialize control
tV_ReadNFC = (TextView) findViewById(R.id.tV_ReadNFC);
//initialise nfc adapter
nfcAdapt = NfcAdapter.getDefaultAdapter(this);
//check is NFC adapter initialized null when device doesn't support NFC
if (nfcAdapt == null) {
// device deosn't support nfc
Toast.makeText(this, "your device doesn't support NFC.", Toast.LENGTH_SHORT).show();
finish();
return;
}
//check is NFC adapter feature enabled
if (!nfcAdapt.isEnabled()) {
tV_ReadNFC.setText("NFC is disabled.");
} else {
tV_ReadNFC.setText(R.string.attachNFCToRead);
}
handleIntent(getIntent());
}
#Override
protected void onResume() {
super.onResume();
}
#Override
protected void onPause() {
//Call this before onPause, to avoid an IllegalArgumentException.
stopForegroundDispatch(this, nfcAdapt);
super.onPause();
}
#Override
protected void onNewIntent(Intent intent) {
handleIntent(intent);
}
private void handleIntent(Intent intent) {
//get action from intent
String action = intent.getAction();
//is action matches the NDEF_DISCOVERED
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
//what is the mime type
String type = intent.getType();
//is text plain or not
if (MIMETYPE_TEXT_PLAIN.equals(type)) {
//create tag instance and retrieve extended data from intent
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
//execute background task
new NdefReaderBgTask().execute(tag);
} else {
Log.d(TAG, "mime type is not text/plain: " + type);
}
}
//is action matches the ACTION_TECH_DISCOVERED
else if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)) {
// In case we would still use the Tech Discovered Intent
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
//get the available technologies
String[] techList = tag.getTechList();
//get class name
String searchedTech = Ndef.class.getName();
for (String tech : techList) {
//tag matched then execute background task
if (searchedTech.equals(tech)) {
new NdefReaderBgTask().execute(tag);
break;
}
}
}
}
/**
* #param act The corresponding {#link Activity} requesting the foreground dispatch.
* #param adp The {#link NfcAdapter} used for the foreground dispatch.
*/
public static void requestForegroundDispatch(final Activity act, NfcAdapter adp) {
//create instance of intent
final Intent intent = new Intent(act.getApplicationContext(), act.getClass());
//set flags on top
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
//crate instance of pending intent
final PendingIntent pendingIntent = PendingIntent.getActivity(act.getApplicationContext(), 0, intent, 0);
//create intent filters array
IntentFilter[] filters = new IntentFilter[1];
//create 2D array of techlist String
String[][] techList = new String[][]{};
// Note: This is the same filter as in our manifest.
filters[0] = new IntentFilter();
filters[0].addAction(NfcAdapter.ACTION_NDEF_DISCOVERED);
filters[0].addCategory(Intent.CATEGORY_DEFAULT);
try {
//add data type
filters[0].addDataType(MIMETYPE_TEXT_PLAIN);
} catch (MalformedMimeTypeException e) {
//throw exception on different mime type
throw new RuntimeException("Check your mime type.");
}
//enable foreground dispatch to current activity
adp.enableForegroundDispatch(act, pendingIntent, filters, techList);
}
public static void stopForegroundDispatch(final Activity act, NfcAdapter adp) {
adp.disableForegroundDispatch(act);
}
private class NdefReaderBgTask extends AsyncTask<Tag, Void, String> {
#Override
protected String doInBackground(Tag... params) {
Tag tag = params[0];
Ndef ndef = Ndef.get(tag);
if (ndef == null) {
// when NDEF is not supported by this Tag.
return null;
}
//Get the NdefMessage that was read from the tag at discovery time.
NdefMessage ndefMessage = ndef.getCachedNdefMessage();
//Get the NDEF Records inside this NDEF Message.
NdefRecord[] records = ndefMessage.getRecords();
for (NdefRecord ndefRecord : records) {
if (ndefRecord.getTnf() == NdefRecord.TNF_WELL_KNOWN && Arrays.equals(ndefRecord.getType(), NdefRecord.RTD_TEXT)) {
try {
return readNDEFRecordText(ndefRecord);
} catch (UnsupportedEncodingException e) {
Log.e(TAG, "Unsupported Encoding", e);
}
}
}
return null;
}
private String readNDEFRecordText(NdefRecord record) throws UnsupportedEncodingException {
// get record pay load variable length
byte[] payload = record.getPayload();
// Get the Text Encoding
String textEncoding = ((payload[0] & 128) == 0) ? "UTF-8" : "UTF-16";
// Get the Language Code
int languageCodeLength = payload[0] & 0063;
// String languageCode = new String(payload, 1, languageCodeLength, "US-ASCII");
// e.g. "en"
// Get the Text
return new String(payload, languageCodeLength + 1, payload.length - languageCodeLength - 1, textEncoding);
}
#Override
protected void onPostExecute(String result) {
if (result != null) {
tV_ReadNFC.setText("Content in your TAG: " + result);
}
}
}
}
Using the foreground dispatch to receive the NFC event is a good start.
Identifying a specific tag very much depends on what you need in your context:
You could match tag IDs. This is certainly the easiest approach as every tag exposes some ID that is used by the NFC device during tag enumeration and anti-collision. However, this approach has some limitations:
Not all tags expose static IDs. Some tags generate a fresh random ID upon power-up. Identifying such a tag from its ID is therefore impossible.
Depending on the protocol, IDs may have different lengths. E.g. an ISO 14443A (NfcA) tag may have a 4-byte, 7-byte or 10-byte UID. Thus, you have to consider this when creating your database of valid tags.
You can't auto-start your app based on a specific ID.
You have to record every allowed ID in some database and can't easily define a large set of allowed tags.
You could use a specific NDEF record on the tag. In my opinion this is the prefered way to go.
I would refrain from using the Text record type (or text/* MIME type records) as these types are supposed to be used to transport human-readable and (more importantly) human-interpreted text.
Instead, I would suggest that you define your own NFC Forum external type name (specifications are available for free from NFC Forum) and create a record using that type name.
This allows you to easily auto-start your (and only your) app by filtering for that particular type name.
You can start the countdown based on either presence of an NDEF record with that particular type name, or
you can add a specific data payload to your tags (e.g. an custom identifier) to allow only certain tags that have this type name to start the countdown or to distinguish between different tags carrying a record with that type name.
For the ID matching scenario, I would suggest that you modify the foreground dispatch activation like this (don't forget to actually activate the foreground dispatch in onResume()):
public static void requestForegroundDispatch(final Activity act, NfcAdapter adp) {
final Intent pendingIntent = PendingIntent.getActivity(act, 0, new Intent(act, act.getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
IntentFilter[] filters = new IntentFilter[] { new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED) };
String[][] techList = new String[][] { new String[] { NfcA.class.getName() } };
adp.enableForegroundDispatch(act, pendingIntent, filters, techList);
}
This will match any ISO 14443 Type A tag (like the NTAG203).
Then you could retrieve the tag's ID in your handleIntent method like this:
private void handleIntent(Intent intent) {
String action = intent.getAction();
if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)) {
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
byte[] id = tag.getId();
// do something with the ID
}
}
I want to know how my android users are getting to the play store link of my app.
To do this I have integrated the Google Analytics API, but the installation intent isn't called and I can't get the utm_source, utm_campaign ... parameters in the link built with the google play url builder
So i'm trying to do this with my custom intent like this :
1: The android manifest :
<receiver android:name="com.appehour.InstallReceiver" android:exported="true">
<intent-filter>
<action android:name="com.android.vending.INSTALL_REFERRER" android:exported="true"/>
</intent-filter>
</receiver>
2: the InstallReceiver class
public class InstallReceiver extends BroadcastReceiver {
private String
utm_compaign ,
utm_source,
utm_medium,
utm_term,
utm_content,
deviceId;
private static String url, installTimeStamp;
public static final String PREF_TRACK_INSTALL_RECEIVER_DATAS = "datas_receiver_install",
PREF_DEVICE_ID = "pref_device_id",
PREF_COMPAIGN = "pref_compaign",
PREF_SOURCE = "pref_source",
PREF_MEDIUM = "pref_medium",
PREF_TERM = "pref_term",
PREF_CONTENT = "pref_content",
PREF_INSTALL_TIME_STAMP = "pref_install_time_stamp",
PREF_DATA_STORED = "pref_datas_stored";
protected JSONObject jsonSend , jsonObjRecv;
private boolean installParamsSend = false;
#SuppressLint("NewApi")
#Override
public void onReceive(Context context, Intent intent) {
TimeZone timeZone = TimeZone.getDefault();
installTimeStamp = String.valueOf(System.currentTimeMillis()) ;
deviceId = Secure.getString(context.getContentResolver(),Secure.ANDROID_ID);
//****************************** Tris des datas reçus par le brodcast ********************************//
String referrer = intent.getStringExtra("referrer");
//the paramters are separated by this : %3D
// uriTokens store all the paramaters with her value
String[] uriTokens = referrer.split("%3D");
for(int i=0;i<uriTokens.length;i++){
//the parameter name and the value are separated
String[] valTokens = uriTokens[i].split("%26");
if (valTokens[0].equals("utm_compaign"))
utm_compaign = valTokens[1];
else if (valTokens[0].equals("utm_source"))
utm_source = valTokens[1];
else if (valTokens[0].equals("utm_medium"))
utm_medium = valTokens[1];
else if (valTokens[0].equals("utm_term"))
utm_term = valTokens[1];
else if (valTokens[0].equals("utm_content"))
utm_content = valTokens[1];
}
//******************************************************************************************************//
Log.d(InstallReceiver.this.getClass().getSimpleName(),
"utm_compaign = "+utm_compaign+
"| utm_source = "+utm_source+
"| utm_medium = "+utm_medium+
"| utm_term = "+utm_term+
"| utm_content = "+utm_content+
"| device_id = "+deviceId+
"| installTimeStamp ="+installTimeStamp);
When I simulate the app installation with adb shell:
adb shell am broadcast -a com.android.vending.INSTALL_REFERRER -n com.appehour.jdm/com.appehour.InstallReceiver --es "referrer" "utm_source%26testSource%3Dutm_compaign%268656"
I get my data. But when I put my app on the store, the data are not recovered.
Any idea what the issue is?
Thanks
I want to implement install referrer track and want referrer parameter and store in back end database i have seen many exmple or question as on like Get Android Google Analytics referrer tag or Android Google Analytics Campaign tracking not appearing but not get a way i have generated links to and try the code
package SimpleDemo.ReferralTrack;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
public class ReferralReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
// Workaround for Android security issue: http://code.google.com/p/android/issues/detail?id=16006
try
{
final Bundle extras = intent.getExtras();
if (extras != null) {
extras.containsKey(null);
}
}
catch (final Exception e) {
return;
}
Map<String, String> referralParams = new HashMap<String, String>();
// Return if this is not the right intent.
if (! intent.getAction().equals("com.android.vending.INSTALL_REFERRER")) { //$NON-NLS-1$
return;
}
String referrer = intent.getStringExtra("referrer"); //$NON-NLS-1$
if( referrer == null || referrer.length() == 0) {
return;
}
try
{ // Remove any url encoding
referrer = URLDecoder.decode(referrer, "x-www-form-urlencoded"); //$NON-NLS-1$
}
catch (UnsupportedEncodingException e) { return; }
// Parse the query string, extracting the relevant data
String[] params = referrer.split("&"); // $NON-NLS-1$
for (String param : params)
{
String[] pair = param.split("="); // $NON-NLS-1$
referralParams.put(pair[0], pair[1]);
}
ReferralReceiver.storeReferralParams(context, referralParams);
}
private final static String[] EXPECTED_PARAMETERS = {
"utm_source",
"utm_medium",
"utm_term",
"utm_content",
"utm_campaign"
};
private final static String PREFS_FILE_NAME = "ReferralParamsFile";
/*
* Stores the referral parameters in the app's sharedPreferences.
* Rewrite this function and retrieveReferralParams() if a
* different storage mechanism is preferred.
*/
public static void storeReferralParams(Context context, Map<String, String> params)
{
SharedPreferences storage = context.getSharedPreferences(ReferralReceiver.PREFS_FILE_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = storage.edit();
for(String key : ReferralReceiver.EXPECTED_PARAMETERS)
{
String value = params.get(key);
if(value != null)
{
editor.putString(key, value);
}
}
editor.commit();
}
/*
* Returns a map with the Market Referral parameters pulled from the sharedPreferences.
*/
public static Map<String, String> retrieveReferralParams(Context context)
{
HashMap<String, String> params = new HashMap<String, String>();
SharedPreferences storage = context.getSharedPreferences(ReferralReceiver.PREFS_FILE_NAME, Context.MODE_PRIVATE);
for(String key : ReferralReceiver.EXPECTED_PARAMETERS)
{
String value = storage.getString(key, null);
if(value != null)
{
params.put(key, value);
}
}
return params;
}
}
After that i have try in my activity
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(DemoActivity.this);
String referrers1 =preferences.getString("ga_campaign", "0");
Map<String, String> retrieveReferralParams=ReferralReceiver.retrieveReferralParams(DemoActivity.this);
String referrers2= retrieveReferralParams.get("utm_source");
String referrers3= retrieveReferralParams.get("utm_medium");
String referrers4= retrieveReferralParams.get("utm_term");
String referrers5= retrieveReferralParams.get("utm_content");
String referrers6= retrieveReferralParams.get("utm_campaign");
tv.setText(referrers1+" "+referrers2+" "+referrers3+" "+referrers4+" "+referrers5+" "+referrers6+" ");
on button click but not get desired output
i want something like from
"https://play.google.com/store/apps/details?id=com.lifestreet.android.TestInstallationIntent&referrer=bb%3DAAAAAAAAAA&feature=search_result%22"
Ans
referrer=bb
any help me highly appreciated
Thanks in advance.
Not sure that Google lets you send arbitrary information. Try using the generator to create the url.
https://developers.google.com/analytics/devguides/collection/android/devguide#google-play-builder
I have had a similar issue. Found it to be lifecycle problem: the onReceive of the install_referrer receivers are invoked AFTER my app's onResume(), on the SAME main thread, so any attempt to read the referrer file during onResume() fails. Here is the logcat to prove it, this was 100% reproducible over and over on 2 devices using Android 4.2.1 and 4.4.2:
First, play store broadcasts the referrer to the package on a separate (store) process:
11-04 14:17:51.558: D/Finsky(1737): [1] ReferrerRebroadcaster.doBroadcastInstallReferrer: Delivered referrer for com.xxx.demo
The app onResume() - still no activation of the broadcast receivers! S
11-04 14:17:51.888: D/XXX Main Activity(22730): onResume
The app tries to read the referrer (which the receivers should have stored using getSharedPreferences.putString):
11-04 14:17:51.958: I/XXX(22730): Extracted install referrer:
Only now the receivers are invoked on the main thread and will shortly try to write the referrer to a file:
11-04 14:17:51.918: I/XXX(22730): Received install referrer: abcdefg
As you can see, onResume() has no chance to actually read the file, so the extraction yields nothing. However, if I close the app and reopen it, onResume is now able to find the file and the referrer string gets processed - but not on first launch :)
Hope this helps!
Google Analytics uses arbitrary constants in their SDK.
for campaing_source is &cs.
Created BroadcastReceiver which displays application name and version number on install/ uninstall of any application. But i am getting package name through intent.getData(). But when i am trying to find the name of that application using packagemanager it's throwing an exception in all the cases Install/ Uninstall/ Replaced. What could be the possible problem and how can this be fixed?
CODE:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.widget.Toast;
public class ApplicationStatusNotification extends BroadcastReceiver {
/**
* This method receives message for any application status(Install/ Uninstall) and display details.
*/
#Override
public void onReceive(Context context, Intent intent) {
// Get application status(Install/ Uninstall)
boolean applicationStatus = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
String toastMessage = null;
// Check if the application is install or uninstall and display the message accordingly
if(intent.getAction().equals("android.intent.action.PACKAGE_INSTALL")){
// Application Install
toastMessage = "PACKAGE_INSTALL: "+ intent.getData().toString() + getApplicationName(context, intent.getData().toString(), PackageManager.GET_UNINSTALLED_PACKAGES);
}else if(intent.getAction().equals("android.intent.action.PACKAGE_REMOVED")){
// Application Uninstall
toastMessage = "PACKAGE_REMOVED: "+ intent.getData().toString() + getApplicationName(context, intent.getData().toString(), PackageManager.GET_UNINSTALLED_PACKAGES);
}else if(intent.getAction().equals("android.intent.action.PACKAGE_REPLACED")){
// Application Replaced
toastMessage = "PACKAGE_REPLACED: "+ intent.getData().toString() + getApplicationName(context, intent.getData().toString(), PackageManager.GET_UNINSTALLED_PACKAGES);
}
//Display Toast Message
if(toastMessage != null){
Toast.makeText(context, toastMessage, Toast.LENGTH_LONG).show();
}
}
/**
* This method get application name name from application package name
*/
private String getApplicationName(Context context, String data, int flag) {
final PackageManager pckManager = context.getPackageManager();
ApplicationInfo applicationInformation;
try {
applicationInformation = pckManager.getApplicationInfo(data, flag);
} catch (PackageManager.NameNotFoundException e) {
applicationInformation = null;
}
final String applicationName = (String) (applicationInformation != null ? pckManager.getApplicationLabel(applicationInformation) : "(unknown)");
return applicationName;
}
}
I followed this example where BroadcastReceiver is introduced as follows;
<receiver android:name="PackageChangeReceiver">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_ADDED"/>
<action android:name="android.intent.action.PACKAGE_REPLACED"/>
<action android:name="android.intent.action.PACKAGE_REMOVED"/>
<data android:scheme="package"/>
</intent-filter>
</receiver>
Now once PackageChangeReceiver.onReceive(..) is called, Intent.getData() Uri contains something around; package:my.test.package which is returned by Uri.toString(). For searching this ApplicationInfo using PackageManager you should extract package name only which can be retrieved by Uri.getSchemeSpecificPart() which should give you my.test.package only.
Also, based on quick testing, it seems very likely that after package removal there's no ApplicationInfo available anymore.