{"_id":"55d1f1c0486de50d00326f17","__v":71,"parentDoc":null,"project":"5540ce1b31827a0d007ab1cc","user":"5540cdbf5cf9682100d61a97","category":{"_id":"5540e5f131827a0d007ab212","__v":15,"project":"5540ce1b31827a0d007ab1cc","pages":["5540e66b31827a0d007ab217","5540e67731827a0d007ab219","55ac917b5863b817008ae3b4","55acaa4c6b4ff90d00784a92","55acb96418eefd0d0071d553","55acc8aa18eefd0d0071d596","55accd2818eefd0d0071d5a8","55acd06518eefd0d0071d5b6","55acddd7fb7b3c19003739cc","55ace14bfb7b3c19003739d3","55ace3a9fb7b3c19003739d7","55acea24f93f0c0d005b880f","55acf15bf93f0c0d005b8821","55acf3cd18eefd0d0071d5fb","55d1f1c0486de50d00326f17"],"version":"5540ce1c31827a0d007ab1cf","sync":{"url":"","isSync":false},"reference":false,"createdAt":"2015-04-29T14:08:49.271Z","from_sync":false,"order":4,"slug":"android","title":"Android"},"version":{"_id":"5540ce1c31827a0d007ab1cf","project":"5540ce1b31827a0d007ab1cc","__v":31,"createdAt":"2015-04-29T12:27:08.390Z","releaseDate":"2015-04-29T12:27:08.390Z","categories":["5540ce1c31827a0d007ab1d0","5540d91bbb9e762d00f594ad","5540e5f131827a0d007ab212","5540e5febb9e762d00f594d3","5540e61331827a0d007ab213","5540e6195cf9682100d61afa","5540e62631827a0d007ab214","5540e63031827a0d007ab215","5540e63531827a0d007ab216","5540e63e5cf9682100d61afc","5540e6445cf9682100d61afd","5540e64a5cf9682100d61afe","55a4ff5b2e70c0250038050f","55acb28318eefd0d0071d504","55ae1abe8576b92300291c80","55ae453ef302af23000ac109","55af586d555b900d0036d296","55af91dac8a85321007a53c3","55b9fee204775a2f00628071","55b9ff0e04775a2f00628072","55b9ff4604775a2f00628073","55b9ff5fd72d1e1900276a38","55b9ff7f04775a2f00628074","55b9ff90eb08801900f833e5","55b9ffa5d72d1e1900276a39","55b9ffca04775a2f00628075","55b9fffdd72d1e1900276a3a","56bc2f033ee9e70d008b46af","56c2f6efbbf9ec2d00e0fe4f","57595bbb18760817001e8bbe","57d8d9793916800e003dde53"],"is_deprecated":false,"is_hidden":false,"is_beta":false,"is_stable":true,"codename":"","version_clean":"1.0.0","version":"1.0"},"updates":["560aac62f6994b0d0023bc6d"],"next":{"pages":[],"description":""},"createdAt":"2015-08-17T14:37:52.556Z","link_external":false,"link_url":"","githubsync":"","sync_unique":"","hidden":true,"api":{"results":{"codes":[]},"settings":"","auth":"required","params":[],"url":""},"isReference":false,"order":5,"body":"* [In App Purchase Tracking](http://docs.pushwoosh.com/docs/androidmanifestxml-modifications#in-app-purchase-tracking)\n* [Deep Linking](http://docs.pushwoosh.com/docs/androidmanifestxml-modifications#deep-linking)\n* [Geozones push notifications](http://docs.pushwoosh.com/docs/customising-android-sdk-50#geozones-push-notification)\n* [Using Beacons](http://docs.pushwoosh.com/docs/androidmanifestxml-modifications#using-beacons)\n* [Using Local Notifications](http://docs.pushwoosh.com/docs/androidmanifestxml-modifications#using-local-notifications-with-pushwoosh)\n* [Using Badge Number](http://docs.pushwoosh.com/docs/androidmanifestxml-modifications#using-badge-number-on-android)\n* [Opening custom activity](http://docs.pushwoosh.com/docs/androidmanifestxml-modifications#opening-custom-activity)\n* [Controlling log level](http://docs.pushwoosh.com/docs/androidmanifestxml-modifications#controlling-log-level)\n* [Using Proguard](http://docs.pushwoosh.com/docs/androidmanifestxml-modifications#using-proguard)\n* [Using Custom Push Receiver](http://docs.pushwoosh.com/docs/androidmanifestxml-modifications#using-custom-push-broadcast-receiver-in-android)\n* [Customizing push notifications](http://docs.pushwoosh.com/docs/androidmanifestxml-modifications#customizing-push-notifications)\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"In App Purchase tracking\"\n}\n[/block]\nIn order to track in-app purchases you should call the `trackInAppRequest` method of the `PushManager` class when a user buys a product:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"public static void trackInAppRequest(Context context, String sku, BigDecimal price, String currency, Date purchaseTime)\",\n      \"language\": \"java\"\n    }\n  ]\n}\n[/block]\n  * `sku` – purchased product ID\n  * `price` – price of the product\n  * `currency` – currency of the price (ex: “USD”)\n  * `purchaseTime` – time of the purchase (ex: new Date())\n\nExample:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"pushManager.trackInAppRequest(context, \\\"com.example.inapp1\\\", \\\"1.99\\\", \\\"USD\\\", new Date());\",\n      \"language\": \"java\"\n    }\n  ]\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Deep linking\"\n}\n[/block]\nIn your activity that will handle the deep link add <data> tag with the scheme, host and pathPrefix parameters.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"<activity\\n          android:name=\\\".PromoActivity\\\"\\n          android:label=\\\"PromoActivity\\\">\\n    <intent-filter>\\n        <action android:name=\\\"android.intent.action.VIEW\\\" />\\n        <category android:name=\\\"android.intent.category.DEFAULT\\\" />\\n        <category android:name=\\\"android.intent.category.BROWSABLE\\\" />\\n\\n        <data android:scheme=\\\"com.pushwoosh\\\"\\n          android:host=\\\"promotion\\\"\\n          android:pathPrefix=\\\"\\\" />\\n    </intent-filter>\\n</activity>\\n\",\n      \"language\": \"xml\"\n    }\n  ]\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"info\",\n  \"body\": \"Note that deep link page name (*promotion* in the example) goes to the **host** field, **not** **pathPrefix**.\"\n}\n[/block]\nIn the example above the deep link will open PromoActivity. The basic implementation below  displays alert with promo id value for the sake of simplicity. In your application it could definitely do something useful!\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"public class PromoActivity extends Activity\\n{\\n\\t\\t:::at:::Override\\n\\t\\tprotected void onCreate(Bundle savedInstanceState)\\n\\t\\t{\\n\\t\\t\\t\\tsuper.onCreate(savedInstanceState);\\n\\n\\t\\t\\t\\tsetContentView(R.layout.deep_link);\\n\\t\\t\\t\\tsetTitle(\\\"Deep link activity\\\");\\n\\t\\t\\n\\t\\t\\t\\tIntent intent = getIntent();\\n\\t  \\t  String action = intent.getAction();\\n\\t    \\tUri data = intent.getData();\\n\\t    \\n\\t\\t    if (TextUtils.equals(action, Intent.ACTION_VIEW))\\n\\t\\t    {\\n\\t  \\t\\t  \\topenUrl(data);\\n\\t\\t    }\\n\\t\\t}\\n\\t\\n\\t\\tprivate void openUrl(Uri uri) \\n\\t\\t{\\n\\t\\t\\t\\tString promoId = uri.getQueryParameter(\\\"id\\\");\\n\\t\\t\\t\\tToast.makeText(getApplicationContext(), promoId, Toast.LENGTH_LONG).show();\\n\\t\\t}\\n}\",\n      \"language\": \"java\"\n    }\n  ]\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Geozones push notifications\"\n}\n[/block]\nAdd the following changes to AndroidManifest.xml.\nYou should also call **startTrackingGeoPushes()** method of PushManager object. Please see ([Pushwoosh Android SDK API](https://github.com/Pushwoosh/pushwoosh-android-sdk/tree/master/Documentation)).\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"<!-- Geo location permissions: -->\\n<uses-permission android:name=\\\"android.permission.ACCESS_COARSE_LOCATION\\\" />\\n<uses-permission android:name=\\\"android.permission.ACCESS_FINE_LOCATION\\\" />\",\n      \"language\": \"xml\"\n    }\n  ]\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Using Beacons\"\n}\n[/block]\n**1.** Add Bluetooth permissions to your manifest file as follows:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"<!-- Bluetooth permissions: -->\\n<uses-permission android:name=\\\"android.permission.BLUETOOTH\\\"/>\\n<uses-permission android:name=\\\"android.permission.BLUETOOTH_ADMIN\\\"/>\",\n      \"language\": \"xml\"\n    }\n  ]\n}\n[/block]\n**2.** Use the following methods of the PushManager in order to enable and disable scanning for available iBeacons in the area:\n  * `public void startTrackingBeaconPushes();`\n  * `public void stopTrackingBeaconPushes();` \n\nPlease see ([Pushwoosh Android SDK API](https://github.com/Pushwoosh/pushwoosh-android-sdk/tree/master/Documentation)).\n\n**3.** The `public static void setBeaconBackgroundMode(Context context, boolean backgroundMode)` method notifies the iBeacon service that the IBeaconConsumer is either moving to background mode or foreground mode. When in background mode, BluetoothLE scans to look for iBeacons are executed less frequently in order to save battery life.\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Using Local Notifications with Pushwoosh\"\n}\n[/block]\nIf you use Pushwoosh Local Notifications API add `RECEIVE_BOOT_COMPLETED` permission to your **AndroidManifest.xml**:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"<uses-permission android:name=\\\"android.permission.RECEIVE_BOOT_COMPLETED\\\"/>\",\n      \"language\": \"xml\"\n    }\n  ]\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Using Badge Number on Android\"\n}\n[/block]\nPushwoosh supports setting badge number on the app icon shortcut for the following Android launchers:\n**Sony, Samsung, LG, HTC, Xiaomi, ASUS, ADW, APEX, NOVA, HUAWEI, ZUK, OPPO**\n\nYou need to add following permissions to your AndroidManifest.xml\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"<!-- for Samsung -->\\n<uses-permission android:name=\\\"com.sec.android.provider.badge.permission.READ\\\"/>\\n<uses-permission android:name=\\\"com.sec.android.provider.badge.permission.WRITE\\\"/>\\n\\n<!--for htc-->\\n<uses-permission android:name=\\\"com.htc.launcher.permission.READ_SETTINGS\\\"/>\\n<uses-permission android:name=\\\"com.htc.launcher.permission.UPDATE_SHORTCUT\\\"/>\\n\\n<!--for sony-->\\n<uses-permission android:name=\\\"com.sonyericsson.home.permission.BROADCAST_BADGE\\\"/>\\n<uses-permission android:name=\\\"com.sonymobile.home.permission.PROVIDER_INSERT_BADGE\\\"/>\\n\\n<!--for apex-->\\n<uses-permission android:name=\\\"com.anddoes.launcher.permission.UPDATE_COUNT\\\"/>\\n\\n<!--for solid-->\\n<uses-permission android:name=\\\"com.majeur.launcher.permission.UPDATE_BADGE\\\"/>\\n\\n<!--for huawei-->\\n<uses-permission android:name=\\\"com.huawei.android.launcher.permission.CHANGE_BADGE\\\"/>\\n<uses-permission android:name=\\\"com.huawei.android.launcher.permission.READ_SETTINGS\\\"/>\\n<uses-permission android:name=\\\"com.huawei.android.launcher.permission.WRITE_SETTINGS\\\"/>\\n\\n<!--for ZUK-->\\n<uses-permission android:name=\\\"android.permission.READ_APP_BADGE\\\"/>\\n\\n<!--for OPPO-->\\n<uses-permission android:name=\\\"com.oppo.launcher.permission.READ_SETTINGS\\\"/>\\n<uses-permission android:name=\\\"com.oppo.launcher.permission.WRITE_SETTINGS\\\"/>\",\n      \"language\": \"xml\"\n    }\n  ]\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Opening custom activity\"\n}\n[/block]\nIf you want to start particular activity in response to push notifications add the following **intent-filter** to that activity.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"<activity android:name=\\\"YourActivity\\\">\\n    <intent-filter>\\n        <action android:name=\\\"${applicationId}.MESSAGE\\\"/>\\n        <category android:name=\\\"android.intent.category.DEFAULT\\\"/>\\n    </intent-filter>\\n</activity>\",\n      \"language\": \"xml\"\n    }\n  ]\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Controlling Log Level\"\n}\n[/block]\nIn order to assist with debugging and integration, SDK will print all the requests to the console by default. When you ready for the production build,  add \"*PW_LOG_LEVEL*\" meta-data with value \"*ERROR*\" to the AndroidManifest.xml. This way only information about errors will go to the console. Other option could be one of the following:\n\n*NONE* - No logs from the SDK\n*ERROR* - Display only errors in the console\n*WARN* - Display also a warnings\n*INFO* - Display informational messages\n*DEBUG* - Even debug information is displayed now\n*NOISE* - Everything SDK can print and more\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"<meta-data android:name=\\\"PW_LOG_LEVEL\\\" android:value=\\\"ERROR\\\" />\",\n      \"language\": \"xml\"\n    }\n  ]\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Using Proguard\"\n}\n[/block]\nWhen using Proguard add the following options:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"-keep class com.pushwoosh.** { *; }\\n-keep class com.arellomobile.** { *; }\\n-dontwarn com.pushwoosh.**\\n-dontwarn com.arellomobile.**\",\n      \"language\": \"text\"\n    }\n  ]\n}\n[/block]\nAlso see **Google Play Services** library requirements regarding Proguard here:\nhttps://developers.google.com/android/guides/setup\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Using Custom Push Broadcast Receiver in Android\"\n}\n[/block]\nIf you need to programmatically select which activity to display as a result of push notification, you can create custom broadcast receiver to receive push notification tap event. You also have to add your receiver to AndroidManifest.xml. Then include fully qualified class name of the receiver in metadata under **“PW_NOTIFICATION_RECEIVER”** value.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"<receiver android:name=\\\"your.app.package.NotificationReceiver\\\" />\\n<meta-data android:name=\\\"PW_NOTIFICATION_RECEIVER\\\" android:value=\\\"${notificationReceiverPackage}.NotificationReceiver\\\"/>\\n\",\n      \"language\": \"xml\"\n    }\n  ]\n}\n[/block]\nExample of the receiver (note pre- and post-handling functions):\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"public class NotificationReceiver extends BroadcastReceiver\\n{\\n    public void onReceive(Context context, Intent intent)\\n    {\\n        if (intent == null)\\n            return;\\n \\n        //Let Pushwoosh SDK to pre-handling push (Pushwoosh track stats, opens rich pages, etc.).\\n        //It will return Bundle with a push notification data\\n        Bundle pushBundle = PushManagerImpl.preHandlePush(context, intent);\\n        if(pushBundle == null)\\n            return;\\n             \\n        //get push bundle as JSON object\\n        JSONObject dataObject = PushManagerImpl.bundleToJSON(pushBundle);\\n         \\n        //Get default launcher intent for clarity\\n        Intent launchIntent  = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());\\n        launchIntent.addCategory(\\\"android.intent.category.LAUNCHER\\\");\\n             \\n        launchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);\\n \\n        //Put push notifications payload in Intent\\n        launchIntent.putExtras(pushBundle);\\n        launchIntent.putExtra(PushManager.PUSH_RECEIVE_EVENT, dataObject.toString());\\n \\n        //Start activity!\\n        context.startActivity(launchIntent);\\n         \\n        //Let Pushwoosh SDK post-handle push (track stats, etc.)\\n        PushManagerImpl.postHandlePush(context, intent);\\n    }\\n}\",\n      \"language\": \"java\"\n    }\n  ]\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Customizing push notifications\"\n}\n[/block]\nTo customize the view of push notification alerts you need to create a custom *Factory*.\nInherit from **AbsNotificationFactory** class and override the following methods:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"\\t/**\\n\\t * Generates notification using pushData\\n\\t * @param pushData push params\\n\\t * @return Notification to show\\n\\t */\\n\\tpublic abstract Notification onGenerateNotification(PushData pushData);\\n\\n\\t/**\\n\\t * Callback for notification delivery event\\n\\t *\\n\\t * @param pushData push params\\n\\t */\\n\\tpublic abstract void onPushReceived(PushData pushData);\\n\\n\\t/**\\n\\t * Callback after notification click\\n\\t * @param activity context\\n\\t */\\n\\tpublic abstract void onPushHandle(Activity activity);\",\n      \"language\": \"java\"\n    }\n  ]\n}\n[/block]\nEverything is better with an example!\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"import org.json.JSONArray;\\nimport org.json.JSONException;\\nimport org.json.JSONObject;\\n\\nimport android.app.Activity;\\nimport android.app.Notification;\\nimport android.app.PendingIntent;\\nimport android.content.Intent;\\n\\nimport com.pushwoosh.notification.AbsNotificationFactory;\\nimport com.pushwoosh.notification.PushData;\\n\\nimport android.net.Uri;\\nimport android.support.v4.app.NotificationCompat;\\n\\n/**\\n * Notification factory sample for remote notification actions\\n * Android root params example : { \\\"my_actions\\\" : [ { \\\"title\\\" : \\\"Pushwoosh\\\", \\\"url\\\" : \\\"https://www.pushwoosh.com\\\"  } ] }\\n */\\npublic class NotificationFactorySample extends AbsNotificationFactory\\n{\\n\\t@Override\\n\\tpublic Notification onGenerateNotification(PushData pushData)\\n\\t{\\n\\t\\t//create notification builder\\n\\t\\tNotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(getContext());\\n\\t\\t\\n\\t\\t//set title of notification\\n\\t\\t notificationBuilder.setContentTitle(getContentFromHtml(pushData.getHeader()));\\n\\t\\t\\n\\t\\t//set content of notification\\n\\t\\t  notificationBuilder.setContentText(getContentFromHtml(pushData.getMessage()));\\n\\t\\t\\n\\t\\t//set small icon (usually app icon)\\n\\t\\tnotificationBuilder.setSmallIcon(pushData.getSmallIcon());\\n\\t\\t\\n\\t\\t//set ticket text\\n\\t\\tnotificationBuilder.setTicker(getContentFromHtml(pushData.getTicker()));\\n\\t\\t\\n\\t\\t//display notification now\\n\\t\\tnotificationBuilder.setWhen(System.currentTimeMillis());\\n\\t\\t\\n\\t\\t//add actions to the notification\\n\\t\\taddRemoteActions(notificationBuilder, pushData);\\n\\t\\t\\n\\t\\tif (pushData.getBigPicture() != null)\\n\\t\\t{\\n\\t\\t    //set big image if available\\n\\t\\t\\tnotificationBuilder.setStyle(new NotificationCompat.BigPictureStyle().bigPicture(pushData.getBigPicture()).setSummaryText(getContentFromHtml(pushData.getMessage())));\\n\\t\\t}\\n\\t\\telse\\n\\t\\t{\\n\\t\\t    //otherwise it's big text style\\n\\t\\t    notificationBuilder.setStyle(new NotificationCompat.BigTextStyle().bigText(getContentFromHtml(pushData.getMessage())));\\n\\t\\t}\\n\\t\\t\\n\\t\\t//support icon background color\\n\\t\\tif (pushData.getIconBackgroundColor() != null)\\n\\t\\t{\\n\\t\\t      notificationBuilder.setColor(pushData.getIconBackgroundColor());\\n\\t\\t}\\n\\t\\t\\n\\t\\t//support custom icon\\n\\t\\tif (null != pushData.getLargeIcon())\\n\\t\\t{\\n\\t\\t    notificationBuilder.setLargeIcon(pushData.getLargeIcon());\\n\\t\\t}\\n\\t\\t\\n\\t\\t//build the notification\\n\\t\\tfinal Notification notification = notificationBuilder.build();\\n\\t\\t\\n\\t\\t//add sound\\n\\t\\taddSound(notification, pushData.getSound());\\n\\t\\t\\n\\t\\t//add vibration\\n\\t\\taddVibration(notification, pushData.getVibration());\\n\\t\\t\\n\\t\\t//make it cancelable\\n\\t\\taddCancel(notification);\\n\\t\\t\\n\\t\\t//all done!\\n\\t\\treturn notification;\\n\\t}\\n\\t\\n\\tprivate void addRemoteActions(NotificationCompat.Builder notificationBuilder, PushData pushData)\\n\\t{\\n\\t\\tString actions = pushData.getExtras().getString(\\\"my_actions\\\");\\n\\t\\tif (actions != null)\\n\\t\\t{\\n\\t\\t\\ttry\\n\\t\\t\\t{\\n\\t\\t\\t\\tJSONArray jsonArray = new JSONArray(actions);\\n\\t\\t\\t\\tfor (int i = 0; i < jsonArray.length(); ++i)\\n\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\tJSONObject json = jsonArray.getJSONObject(i);\\n\\t\\t\\t\\t\\tString title = json.getString(\\\"title\\\");\\n\\t\\t\\t\\t\\tString url = json.getString(\\\"url\\\");\\n\\t\\t\\t\\t\\tIntent actionIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));\\n\\t\\t\\t\\t\\tnotificationBuilder.addAction(new NotificationCompat.Action(0, title, PendingIntent.getActivity(getContext(), 0, actionIntent, PendingIntent.FLAG_UPDATE_CURRENT)));\\n\\t\\t\\t\\t}\\n\\t\\t\\t}\\n\\t\\t\\tcatch (JSONException e)\\n\\t\\t\\t{\\n\\t\\t\\t\\te.printStackTrace();\\n\\t\\t\\t}\\n\\t\\t}\\n\\t}\\n\\n\\t@Override\\n\\tpublic void onPushReceived(PushData pushData)\\n\\t{\\n\\t\\t// TODO Auto-generated method stub\\n\\t\\t\\n\\t}\\n\\n\\t@Override\\n\\tpublic void onPushHandle(Activity activity)\\n\\t{\\n\\t\\t// TODO Auto-generated method stub\\n\\t\\t\\n\\t}\\n}\\n\",\n      \"language\": \"java\"\n    }\n  ]\n}\n[/block]\nThe last step is to set your notification Factory to the Push Manager:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"pushManager.setNotificationFactory(new NotificationFactorySample());\",\n      \"language\": \"java\"\n    }\n  ]\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Private Endpoint URL\"\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"success\",\n  \"title\": \"Enterprise only.\"\n}\n[/block]\nPushwoosh provides Private endpoints for Enterprise customers. To set up Private endpoint for iOS SDK you need to add the following to your AndroidManifest.xml file\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"<meta-data android:name=\\\"PushwooshUrl\\\" android:value=\\\"PUSHWOOSH_PRIVATE_ENDPOINT_URL_PROVIDED\\\" />\",\n      \"language\": \"xml\",\n      \"name\": \"AndroidManifest.xml\"\n    }\n  ]\n}\n[/block]","excerpt":"","slug":"androidmanifestxml-modifications","type":"basic","title":"Customizing Android SDK"}

Customizing Android SDK


* [In App Purchase Tracking](http://docs.pushwoosh.com/docs/androidmanifestxml-modifications#in-app-purchase-tracking) * [Deep Linking](http://docs.pushwoosh.com/docs/androidmanifestxml-modifications#deep-linking) * [Geozones push notifications](http://docs.pushwoosh.com/docs/customising-android-sdk-50#geozones-push-notification) * [Using Beacons](http://docs.pushwoosh.com/docs/androidmanifestxml-modifications#using-beacons) * [Using Local Notifications](http://docs.pushwoosh.com/docs/androidmanifestxml-modifications#using-local-notifications-with-pushwoosh) * [Using Badge Number](http://docs.pushwoosh.com/docs/androidmanifestxml-modifications#using-badge-number-on-android) * [Opening custom activity](http://docs.pushwoosh.com/docs/androidmanifestxml-modifications#opening-custom-activity) * [Controlling log level](http://docs.pushwoosh.com/docs/androidmanifestxml-modifications#controlling-log-level) * [Using Proguard](http://docs.pushwoosh.com/docs/androidmanifestxml-modifications#using-proguard) * [Using Custom Push Receiver](http://docs.pushwoosh.com/docs/androidmanifestxml-modifications#using-custom-push-broadcast-receiver-in-android) * [Customizing push notifications](http://docs.pushwoosh.com/docs/androidmanifestxml-modifications#customizing-push-notifications) [block:api-header] { "type": "basic", "title": "In App Purchase tracking" } [/block] In order to track in-app purchases you should call the `trackInAppRequest` method of the `PushManager` class when a user buys a product: [block:code] { "codes": [ { "code": "public static void trackInAppRequest(Context context, String sku, BigDecimal price, String currency, Date purchaseTime)", "language": "java" } ] } [/block] * `sku` – purchased product ID * `price` – price of the product * `currency` – currency of the price (ex: “USD”) * `purchaseTime` – time of the purchase (ex: new Date()) Example: [block:code] { "codes": [ { "code": "pushManager.trackInAppRequest(context, \"com.example.inapp1\", \"1.99\", \"USD\", new Date());", "language": "java" } ] } [/block] [block:api-header] { "type": "basic", "title": "Deep linking" } [/block] In your activity that will handle the deep link add <data> tag with the scheme, host and pathPrefix parameters. [block:code] { "codes": [ { "code": "<activity\n android:name=\".PromoActivity\"\n android:label=\"PromoActivity\">\n <intent-filter>\n <action android:name=\"android.intent.action.VIEW\" />\n <category android:name=\"android.intent.category.DEFAULT\" />\n <category android:name=\"android.intent.category.BROWSABLE\" />\n\n <data android:scheme=\"com.pushwoosh\"\n android:host=\"promotion\"\n android:pathPrefix=\"\" />\n </intent-filter>\n</activity>\n", "language": "xml" } ] } [/block] [block:callout] { "type": "info", "body": "Note that deep link page name (*promotion* in the example) goes to the **host** field, **not** **pathPrefix**." } [/block] In the example above the deep link will open PromoActivity. The basic implementation below displays alert with promo id value for the sake of simplicity. In your application it could definitely do something useful! [block:code] { "codes": [ { "code": "public class PromoActivity extends Activity\n{\n\t\t@Override\n\t\tprotected void onCreate(Bundle savedInstanceState)\n\t\t{\n\t\t\t\tsuper.onCreate(savedInstanceState);\n\n\t\t\t\tsetContentView(R.layout.deep_link);\n\t\t\t\tsetTitle(\"Deep link activity\");\n\t\t\n\t\t\t\tIntent intent = getIntent();\n\t \t String action = intent.getAction();\n\t \tUri data = intent.getData();\n\t \n\t\t if (TextUtils.equals(action, Intent.ACTION_VIEW))\n\t\t {\n\t \t\t \topenUrl(data);\n\t\t }\n\t\t}\n\t\n\t\tprivate void openUrl(Uri uri) \n\t\t{\n\t\t\t\tString promoId = uri.getQueryParameter(\"id\");\n\t\t\t\tToast.makeText(getApplicationContext(), promoId, Toast.LENGTH_LONG).show();\n\t\t}\n}", "language": "java" } ] } [/block] [block:api-header] { "type": "basic", "title": "Geozones push notifications" } [/block] Add the following changes to AndroidManifest.xml. You should also call **startTrackingGeoPushes()** method of PushManager object. Please see ([Pushwoosh Android SDK API](https://github.com/Pushwoosh/pushwoosh-android-sdk/tree/master/Documentation)). [block:code] { "codes": [ { "code": "<!-- Geo location permissions: -->\n<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\" />\n<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\" />", "language": "xml" } ] } [/block] [block:api-header] { "type": "basic", "title": "Using Beacons" } [/block] **1.** Add Bluetooth permissions to your manifest file as follows: [block:code] { "codes": [ { "code": "<!-- Bluetooth permissions: -->\n<uses-permission android:name=\"android.permission.BLUETOOTH\"/>\n<uses-permission android:name=\"android.permission.BLUETOOTH_ADMIN\"/>", "language": "xml" } ] } [/block] **2.** Use the following methods of the PushManager in order to enable and disable scanning for available iBeacons in the area: * `public void startTrackingBeaconPushes();` * `public void stopTrackingBeaconPushes();` Please see ([Pushwoosh Android SDK API](https://github.com/Pushwoosh/pushwoosh-android-sdk/tree/master/Documentation)). **3.** The `public static void setBeaconBackgroundMode(Context context, boolean backgroundMode)` method notifies the iBeacon service that the IBeaconConsumer is either moving to background mode or foreground mode. When in background mode, BluetoothLE scans to look for iBeacons are executed less frequently in order to save battery life. [block:api-header] { "type": "basic", "title": "Using Local Notifications with Pushwoosh" } [/block] If you use Pushwoosh Local Notifications API add `RECEIVE_BOOT_COMPLETED` permission to your **AndroidManifest.xml**: [block:code] { "codes": [ { "code": "<uses-permission android:name=\"android.permission.RECEIVE_BOOT_COMPLETED\"/>", "language": "xml" } ] } [/block] [block:api-header] { "type": "basic", "title": "Using Badge Number on Android" } [/block] Pushwoosh supports setting badge number on the app icon shortcut for the following Android launchers: **Sony, Samsung, LG, HTC, Xiaomi, ASUS, ADW, APEX, NOVA, HUAWEI, ZUK, OPPO** You need to add following permissions to your AndroidManifest.xml [block:code] { "codes": [ { "code": "<!-- for Samsung -->\n<uses-permission android:name=\"com.sec.android.provider.badge.permission.READ\"/>\n<uses-permission android:name=\"com.sec.android.provider.badge.permission.WRITE\"/>\n\n<!--for htc-->\n<uses-permission android:name=\"com.htc.launcher.permission.READ_SETTINGS\"/>\n<uses-permission android:name=\"com.htc.launcher.permission.UPDATE_SHORTCUT\"/>\n\n<!--for sony-->\n<uses-permission android:name=\"com.sonyericsson.home.permission.BROADCAST_BADGE\"/>\n<uses-permission android:name=\"com.sonymobile.home.permission.PROVIDER_INSERT_BADGE\"/>\n\n<!--for apex-->\n<uses-permission android:name=\"com.anddoes.launcher.permission.UPDATE_COUNT\"/>\n\n<!--for solid-->\n<uses-permission android:name=\"com.majeur.launcher.permission.UPDATE_BADGE\"/>\n\n<!--for huawei-->\n<uses-permission android:name=\"com.huawei.android.launcher.permission.CHANGE_BADGE\"/>\n<uses-permission android:name=\"com.huawei.android.launcher.permission.READ_SETTINGS\"/>\n<uses-permission android:name=\"com.huawei.android.launcher.permission.WRITE_SETTINGS\"/>\n\n<!--for ZUK-->\n<uses-permission android:name=\"android.permission.READ_APP_BADGE\"/>\n\n<!--for OPPO-->\n<uses-permission android:name=\"com.oppo.launcher.permission.READ_SETTINGS\"/>\n<uses-permission android:name=\"com.oppo.launcher.permission.WRITE_SETTINGS\"/>", "language": "xml" } ] } [/block] [block:api-header] { "type": "basic", "title": "Opening custom activity" } [/block] If you want to start particular activity in response to push notifications add the following **intent-filter** to that activity. [block:code] { "codes": [ { "code": "<activity android:name=\"YourActivity\">\n <intent-filter>\n <action android:name=\"${applicationId}.MESSAGE\"/>\n <category android:name=\"android.intent.category.DEFAULT\"/>\n </intent-filter>\n</activity>", "language": "xml" } ] } [/block] [block:api-header] { "type": "basic", "title": "Controlling Log Level" } [/block] In order to assist with debugging and integration, SDK will print all the requests to the console by default. When you ready for the production build, add "*PW_LOG_LEVEL*" meta-data with value "*ERROR*" to the AndroidManifest.xml. This way only information about errors will go to the console. Other option could be one of the following: *NONE* - No logs from the SDK *ERROR* - Display only errors in the console *WARN* - Display also a warnings *INFO* - Display informational messages *DEBUG* - Even debug information is displayed now *NOISE* - Everything SDK can print and more [block:code] { "codes": [ { "code": "<meta-data android:name=\"PW_LOG_LEVEL\" android:value=\"ERROR\" />", "language": "xml" } ] } [/block] [block:api-header] { "type": "basic", "title": "Using Proguard" } [/block] When using Proguard add the following options: [block:code] { "codes": [ { "code": "-keep class com.pushwoosh.** { *; }\n-keep class com.arellomobile.** { *; }\n-dontwarn com.pushwoosh.**\n-dontwarn com.arellomobile.**", "language": "text" } ] } [/block] Also see **Google Play Services** library requirements regarding Proguard here: https://developers.google.com/android/guides/setup [block:api-header] { "type": "basic", "title": "Using Custom Push Broadcast Receiver in Android" } [/block] If you need to programmatically select which activity to display as a result of push notification, you can create custom broadcast receiver to receive push notification tap event. You also have to add your receiver to AndroidManifest.xml. Then include fully qualified class name of the receiver in metadata under **“PW_NOTIFICATION_RECEIVER”** value. [block:code] { "codes": [ { "code": "<receiver android:name=\"your.app.package.NotificationReceiver\" />\n<meta-data android:name=\"PW_NOTIFICATION_RECEIVER\" android:value=\"${notificationReceiverPackage}.NotificationReceiver\"/>\n", "language": "xml" } ] } [/block] Example of the receiver (note pre- and post-handling functions): [block:code] { "codes": [ { "code": "public class NotificationReceiver extends BroadcastReceiver\n{\n public void onReceive(Context context, Intent intent)\n {\n if (intent == null)\n return;\n \n //Let Pushwoosh SDK to pre-handling push (Pushwoosh track stats, opens rich pages, etc.).\n //It will return Bundle with a push notification data\n Bundle pushBundle = PushManagerImpl.preHandlePush(context, intent);\n if(pushBundle == null)\n return;\n \n //get push bundle as JSON object\n JSONObject dataObject = PushManagerImpl.bundleToJSON(pushBundle);\n \n //Get default launcher intent for clarity\n Intent launchIntent = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());\n launchIntent.addCategory(\"android.intent.category.LAUNCHER\");\n \n launchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);\n \n //Put push notifications payload in Intent\n launchIntent.putExtras(pushBundle);\n launchIntent.putExtra(PushManager.PUSH_RECEIVE_EVENT, dataObject.toString());\n \n //Start activity!\n context.startActivity(launchIntent);\n \n //Let Pushwoosh SDK post-handle push (track stats, etc.)\n PushManagerImpl.postHandlePush(context, intent);\n }\n}", "language": "java" } ] } [/block] [block:api-header] { "type": "basic", "title": "Customizing push notifications" } [/block] To customize the view of push notification alerts you need to create a custom *Factory*. Inherit from **AbsNotificationFactory** class and override the following methods: [block:code] { "codes": [ { "code": "\t/**\n\t * Generates notification using pushData\n\t * @param pushData push params\n\t * @return Notification to show\n\t */\n\tpublic abstract Notification onGenerateNotification(PushData pushData);\n\n\t/**\n\t * Callback for notification delivery event\n\t *\n\t * @param pushData push params\n\t */\n\tpublic abstract void onPushReceived(PushData pushData);\n\n\t/**\n\t * Callback after notification click\n\t * @param activity context\n\t */\n\tpublic abstract void onPushHandle(Activity activity);", "language": "java" } ] } [/block] Everything is better with an example! [block:code] { "codes": [ { "code": "import org.json.JSONArray;\nimport org.json.JSONException;\nimport org.json.JSONObject;\n\nimport android.app.Activity;\nimport android.app.Notification;\nimport android.app.PendingIntent;\nimport android.content.Intent;\n\nimport com.pushwoosh.notification.AbsNotificationFactory;\nimport com.pushwoosh.notification.PushData;\n\nimport android.net.Uri;\nimport android.support.v4.app.NotificationCompat;\n\n/**\n * Notification factory sample for remote notification actions\n * Android root params example : { \"my_actions\" : [ { \"title\" : \"Pushwoosh\", \"url\" : \"https://www.pushwoosh.com\" } ] }\n */\npublic class NotificationFactorySample extends AbsNotificationFactory\n{\n\t@Override\n\tpublic Notification onGenerateNotification(PushData pushData)\n\t{\n\t\t//create notification builder\n\t\tNotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(getContext());\n\t\t\n\t\t//set title of notification\n\t\t notificationBuilder.setContentTitle(getContentFromHtml(pushData.getHeader()));\n\t\t\n\t\t//set content of notification\n\t\t notificationBuilder.setContentText(getContentFromHtml(pushData.getMessage()));\n\t\t\n\t\t//set small icon (usually app icon)\n\t\tnotificationBuilder.setSmallIcon(pushData.getSmallIcon());\n\t\t\n\t\t//set ticket text\n\t\tnotificationBuilder.setTicker(getContentFromHtml(pushData.getTicker()));\n\t\t\n\t\t//display notification now\n\t\tnotificationBuilder.setWhen(System.currentTimeMillis());\n\t\t\n\t\t//add actions to the notification\n\t\taddRemoteActions(notificationBuilder, pushData);\n\t\t\n\t\tif (pushData.getBigPicture() != null)\n\t\t{\n\t\t //set big image if available\n\t\t\tnotificationBuilder.setStyle(new NotificationCompat.BigPictureStyle().bigPicture(pushData.getBigPicture()).setSummaryText(getContentFromHtml(pushData.getMessage())));\n\t\t}\n\t\telse\n\t\t{\n\t\t //otherwise it's big text style\n\t\t notificationBuilder.setStyle(new NotificationCompat.BigTextStyle().bigText(getContentFromHtml(pushData.getMessage())));\n\t\t}\n\t\t\n\t\t//support icon background color\n\t\tif (pushData.getIconBackgroundColor() != null)\n\t\t{\n\t\t notificationBuilder.setColor(pushData.getIconBackgroundColor());\n\t\t}\n\t\t\n\t\t//support custom icon\n\t\tif (null != pushData.getLargeIcon())\n\t\t{\n\t\t notificationBuilder.setLargeIcon(pushData.getLargeIcon());\n\t\t}\n\t\t\n\t\t//build the notification\n\t\tfinal Notification notification = notificationBuilder.build();\n\t\t\n\t\t//add sound\n\t\taddSound(notification, pushData.getSound());\n\t\t\n\t\t//add vibration\n\t\taddVibration(notification, pushData.getVibration());\n\t\t\n\t\t//make it cancelable\n\t\taddCancel(notification);\n\t\t\n\t\t//all done!\n\t\treturn notification;\n\t}\n\t\n\tprivate void addRemoteActions(NotificationCompat.Builder notificationBuilder, PushData pushData)\n\t{\n\t\tString actions = pushData.getExtras().getString(\"my_actions\");\n\t\tif (actions != null)\n\t\t{\n\t\t\ttry\n\t\t\t{\n\t\t\t\tJSONArray jsonArray = new JSONArray(actions);\n\t\t\t\tfor (int i = 0; i < jsonArray.length(); ++i)\n\t\t\t\t{\n\t\t\t\t\tJSONObject json = jsonArray.getJSONObject(i);\n\t\t\t\t\tString title = json.getString(\"title\");\n\t\t\t\t\tString url = json.getString(\"url\");\n\t\t\t\t\tIntent actionIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));\n\t\t\t\t\tnotificationBuilder.addAction(new NotificationCompat.Action(0, title, PendingIntent.getActivity(getContext(), 0, actionIntent, PendingIntent.FLAG_UPDATE_CURRENT)));\n\t\t\t\t}\n\t\t\t}\n\t\t\tcatch (JSONException e)\n\t\t\t{\n\t\t\t\te.printStackTrace();\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void onPushReceived(PushData pushData)\n\t{\n\t\t// TODO Auto-generated method stub\n\t\t\n\t}\n\n\t@Override\n\tpublic void onPushHandle(Activity activity)\n\t{\n\t\t// TODO Auto-generated method stub\n\t\t\n\t}\n}\n", "language": "java" } ] } [/block] The last step is to set your notification Factory to the Push Manager: [block:code] { "codes": [ { "code": "pushManager.setNotificationFactory(new NotificationFactorySample());", "language": "java" } ] } [/block] [block:api-header] { "type": "basic", "title": "Private Endpoint URL" } [/block] [block:callout] { "type": "success", "title": "Enterprise only." } [/block] Pushwoosh provides Private endpoints for Enterprise customers. To set up Private endpoint for iOS SDK you need to add the following to your AndroidManifest.xml file [block:code] { "codes": [ { "code": "<meta-data android:name=\"PushwooshUrl\" android:value=\"PUSHWOOSH_PRIVATE_ENDPOINT_URL_PROVIDED\" />", "language": "xml", "name": "AndroidManifest.xml" } ] } [/block]