1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.android.leanbacklauncher.partnercustomizer; 18 19 import android.app.Activity; 20 import android.app.Notification; 21 import android.app.NotificationManager; 22 import android.app.PendingIntent; 23 import android.content.BroadcastReceiver; 24 import android.content.ComponentName; 25 import android.content.Context; 26 import android.content.Intent; 27 import android.content.IntentFilter; 28 import android.content.pm.ActivityInfo; 29 import android.content.pm.ApplicationInfo; 30 import android.content.pm.PackageInfo; 31 import android.content.pm.PackageManager; 32 import android.content.pm.ResolveInfo; 33 import android.graphics.Bitmap; 34 import android.graphics.BitmapFactory; 35 import android.net.Uri; 36 import android.os.AsyncTask; 37 import android.os.Bundle; 38 import android.os.Handler; 39 import android.provider.Settings; 40 import android.text.TextUtils; 41 42 import java.io.IOException; 43 import java.io.InputStream; 44 import java.net.HttpURLConnection; 45 import java.util.ArrayList; 46 import java.util.List; 47 48 /** 49 * This class posts notifications that are used to populate the Partner Row of the Leanback Launcher 50 * It also allows the system/launcher to find the correct partner customization 51 * package. 52 * 53 * Packages using this broadcast receiver must also be a system app to be used for 54 * partner customization. 55 */ 56 public class PartnerReceiver extends BroadcastReceiver { 57 private static final String ACTION_PARTNER_CUSTOMIZATION = 58 "com.google.android.leanbacklauncher.action.PARTNER_CUSTOMIZATION"; 59 60 private static final String EXTRA_ROW_WRAPPING_CUTOFF = 61 "com.google.android.leanbacklauncher.extra.ROW_WRAPPING_CUTOFF"; 62 63 private static final String PARTNER_GROUP = "partner_row_entry"; 64 private static final String BLACKLIST_PACKAGE = "com.google.android.leanbacklauncher.replacespackage"; 65 66 private static final String TED_PKG_NAME = "com.ted.android.tv"; 67 private static final String PLAY_MOVIES_PKG_NAME = "com.google.android.videos"; 68 69 private Context mContext; 70 private NotificationManager mNotifMan; 71 private PackageManager mPkgMan; 72 73 // Cutoff value for when the Launcher displayes the Partner row as a single 74 // row, or a two row grid. Can be used for correctly positioning the partner 75 // app entries. 76 private int mRowCutoff = 0; 77 78 @Override onReceive(Context context, Intent intent)79 public void onReceive(Context context, Intent intent) { 80 if (mContext == null) { 81 mContext = context; 82 mNotifMan = (NotificationManager) 83 mContext.getSystemService(Context.NOTIFICATION_SERVICE); 84 mPkgMan = mContext.getPackageManager(); 85 } 86 87 String action = intent.getAction(); 88 if (Intent.ACTION_PACKAGE_ADDED.equals(action)|| 89 Intent.ACTION_PACKAGE_REMOVED.equals(action)) { 90 postNotification(getPackageName(intent)); 91 } else if (ACTION_PARTNER_CUSTOMIZATION.equals(action)) { 92 mRowCutoff = intent.getIntExtra(EXTRA_ROW_WRAPPING_CUTOFF, 0); 93 postNotification(TED_PKG_NAME); 94 postNotification(PLAY_MOVIES_PKG_NAME); 95 } 96 } 97 postNotification(String pkgName)98 private void postNotification(String pkgName) { 99 int sort; 100 int resId; 101 int backupResId; 102 int titleId; 103 int backupTitleId; 104 105 switch (pkgName) { 106 case TED_PKG_NAME: 107 sort = 1; 108 resId = R.drawable.ic_ted_banner; 109 backupResId = R.drawable.ic_try_ted_banner; 110 titleId = R.string.ted; 111 backupTitleId = R.string.try_ted; 112 break; 113 case PLAY_MOVIES_PKG_NAME: 114 sort = 2; 115 resId = R.drawable.ic_play_movies_banner; 116 backupResId = R.drawable.ic_try_play_movies_banner; 117 titleId = R.string.play_movies; 118 backupTitleId = R.string.try_play_movies; 119 break; 120 default: 121 return; 122 } 123 124 postNotification(sort, resId, backupResId, titleId, backupTitleId, pkgName); 125 } 126 postNotification(int sort, int resId, int backupResId, int titleId, int backupTitleId, String pkgName)127 private void postNotification(int sort, int resId, int backupResId, 128 int titleId, int backupTitleId, String pkgName) { 129 int id = resId; 130 Intent intent = mPkgMan.getLeanbackLaunchIntentForPackage(pkgName); 131 132 if (intent == null) { 133 titleId = backupTitleId; 134 resId = backupResId; 135 intent = getBackupIntent(pkgName); 136 } 137 138 Notification.Builder bob = new Notification.Builder(mContext); 139 Bundle extras = new Bundle(); 140 extras.putString(BLACKLIST_PACKAGE, pkgName); 141 142 bob.setContentTitle(mContext.getString(titleId)) 143 .setSmallIcon(R.drawable.ic_launcher) 144 .setLargeIcon(BitmapFactory.decodeResource(mContext.getResources(), resId)) 145 .setContentIntent(PendingIntent.getActivity(mContext, 0, intent, 0)) 146 .setCategory(Notification.CATEGORY_RECOMMENDATION) 147 .setGroup(PARTNER_GROUP) 148 .setSortKey(sort+"") 149 .setColor(mContext.getResources().getColor(R.color.partner_color)) 150 .setExtras(extras); 151 152 mNotifMan.notify(id, bob.build()); 153 } 154 getBackupIntent(String pkgName)155 private Intent getBackupIntent(String pkgName) { 156 Intent intent = new Intent(Intent.ACTION_VIEW); 157 intent.setData(Uri.parse("market://details?id=" + pkgName)); 158 159 return intent; 160 } 161 getPackageName(Intent intent)162 private String getPackageName(Intent intent) { 163 Uri uri = intent.getData(); 164 String pkg = uri != null ? uri.getSchemeSpecificPart() : null; 165 return pkg; 166 } 167 168 } 169