Самый простой способ использовать Picasso в уведомлении (иконка)
Я ищу простой способ использовать Picasso для загрузки значка уведомления (который является URL-адресом на удаленной веб-странице). В предыдущей версии приложения я работаю над этим кодом, казалось, работал:
Bitmap speakerPic = null;
try {
speakerPic = new AsyncTask<Void, Void, Bitmap>() {
@Override
protected Bitmap doInBackground(Void... params) {
try {
return Picasso.with(c).load(session.getSpeaker().getPhotoUrl()).get();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}.execute().get(1500, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
if (speakerPic != null) {
builder.setLargeIcon(speakerPic);
} else {
builder.setLargeIcon(BitmapFactory.decodeResource(c.getResources(), R.drawable.ic_launcher));
}
но теперь я получаю TimeOutException каждый раз (и я возвращаюсь к значку по умолчанию в моей папке res). Я должен использовать эту AsyncTask, потому что Picasso (/network) может не произойти в потоке пользовательского интерфейса. (хотя я блокирую поток пользовательского интерфейса для 1.5 сек здесь..).
Я знаю, что Пикассо может обрабатывать remoteviews, но я не хочу использовать пользовательский вид для моего уведомления. Кроме того, я не мог найти способ получить удаленный просмотр для NoticifationIcon.
есть ли способ установить значок моего уведомления просто с помощью Picasso?
5 ответов
Я сам отвечу на вопрос, потому что я нашел достойный способ, используя Picasso и RemoteViews. Протестировано и работает с Picasso 2.5.2:
// Default stuff; making and showing notification
final Context context = getApplicationContext();
final NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
final Notification notification = new NotificationCompat.Builder(context)
.setSmallIcon(R.mipmap.ic_launcher) // Needed for the notification to work/show!!
.setContentTitle("Title of notification")
.setContentText("This is the description of the notification")
// Uncomment if you want to load a big picture
//.setStyle(new NotificationCompat.BigPictureStyle())
.build();
final int notifId = 1337;
notificationManager.notify(notifId, notification);
// Get RemoteView and id's needed
final RemoteViews contentView = notification.contentView;
final int iconId = android.R.id.icon;
// Uncomment for BigPictureStyle, Requires API 16!
//final RemoteViews bigContentView = notification.bigContentView;
//final int bigIconId = getResources().getIdentifier("android:id/big_picture", null, null);
// Use Picasso with RemoteViews to load image into a notification
Picasso.with(getApplicationContext()).load("http://i.stack.imgur.com/CE5lz.png").into(contentView, iconId, notifId, notification);
// Uncomment for BigPictureStyle
//Picasso.with(getApplicationContext()).load("http://i.stack.imgur.com/CE5lz.png").into(bigContentView, iconId, notifId, notification);
//Picasso.with(getApplicationContext()).load("http://i.stack.imgur.com/CE5lz.png").into(bigContentView, bigIconId, notifId, notification);
не уверен, почему ваш код не работает, но его компиляция прекрасна для меня, протестирована на уровне API 21 и Android Studio.
Я сделал несколько изменений в соответствии с моими потребностями, например, удалил временную задержку.
единственные заметные различия является ниже выход в моей logcat и:
Setting airplane_mode_on has moved from android.provider.Settings.System to android.provider.Settings.Global, returning read-only value.
что нормально на основе ссылок:этой и этой
и мой обновленный код:
Bitmap contactPic = null;
final String getOnlinePic = GET_AVATAR;
try {
contactPic = new AsyncTask<Void, Void, Bitmap>() {
@Override
protected Bitmap doInBackground(Void... params) {
try {
return Picasso.with(ctx).load(getOnlinePic)
.resize(200, 200)
.placeholder(R.drawable.ic_action_user_purple_light)
.error(R.drawable.ic_action_user_purple_light)
.get();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}.execute().get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
if (contactPic != null) {
builder.setLargeIcon(contactPic);
} else {
builder.setLargeIcon(BitmapFactory.decodeResource(ctx.getResources(), R.drawable.ic_action_user_purple_light));
}
Я предлагаю самый простой способ интегрировать удаленное изображение внутри вашего уведомления как большой значок с Picasso.
// your notification builder
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(getString(R.string.app_name))
.setContentText(message)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
String picture = "http://i.stack.imgur.com/CE5lz.png";
Bitmap bmp = Picasso.with(getApplicationContext()).load(picture).get();
notificationBuilder.setLargeIcon(bmp);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, notificationBuilder.build());
если вы не хотите ждать, пока Пикассо получает изображение перед отправкой уведомления, одним из решений является отправка уведомления дважды с тем же id, так что NotificationManager
обновит существующее уведомление во второй раз, когда оно будет отправлено.
на практике, в первый раз, используйте заполнитель для setLargeIcon()
, и во второй раз, используйте Bitmap
вы получили от Пикассо Target
.
например, от вашего Activity
:
final Notification.Builder builder = new Notification.Builder(this);
final int id = 0; // change this w/ your notification id
Bitmap placeholder = BitmapFactory.decodeResource(getResources(), R.drawable.your_placeholder_icon);
builder.setContentTitle(title)
.yourFavoriteBuilderMethods(...)
.setLargeIcon(placeholder)
.setDefaults(0); // so that it doesn't ring twice
// mTarget should an instance variable of your class so it doesn't get GC'ed
mTarget = new Target() {
@Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
builder.setLargeIcon(bitmap)
.setDefaults(Notification.DEFAULT_ALL);
// send the notification again to update it w/ the right image
((NotificationManager) (getSystemService(NOTIFICATION_SERVICE)))
.notify(id, builder.build());
}
@Override
public void onBitmapFailed(Drawable errorDrawable) {}
@Override
public void onPrepareLoad(Drawable placeHolderDrawable) {}
};
Picasso.with(this).load(your_image_url_here).into(mTarget);
// send notification for the first time here, w/ placeholder:
((NotificationManager) (getSystemService(NOTIFICATION_SERVICE)))
.notify(id, builder.build());
так как Пикассо нужно будет получить доступ к интернету, не забудьте установить правильное разрешение в манифесте для этого, чтобы работать:
<uses-permission android:name="android.permission.INTERNET" />
Image loading code using Picaso 2.5.2 starts in middle of
this method,besides that all stuff is simple notification code
,просто скопируйте и вставьте, замените "image_url" на фактический url изображения .
private Notification notification;
public void genrateNewsNotification(String title, final int id) {
try {
final Context context=GcmService.this;
final NotificationCompat.Builder mBuilder;
final NotificationManager notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.cancel(id);
Intent notificationIntent = new Intent(context, YourActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
stackBuilder.addParentStack(MainActivity.class);
stackBuilder.addNextIntent(notificationIntent);
final PendingIntent contentIntent =
stackBuilder.getPendingIntent(
id,
PendingIntent.FLAG_UPDATE_CURRENT
);
mBuilder = new NotificationCompat.Builder(context);
mBuilder.setContentTitle("Custom Notification");
mBuilder.setAutoCancel(true);
mBuilder.setPriority(Notification.PRIORITY_MAX);
int currentapiVersion = android.os.Build.VERSION.SDK_INT;
if (currentapiVersion >= Build.VERSION_CODES.LOLLIPOP) {
mBuilder.setSmallIcon(R.drawable.launch_lolipop);
} else {
mBuilder.setSmallIcon(R.drawable.launcher_icon);
}
mBuilder.setContentText(title);
mBuilder.setContentIntent(contentIntent);
notification= mBuilder.build();
// image code starts from here
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
try{
Picasso.with(context).load("image_url")
.into(target);
notificationManager.notify(id, notification);
}
catch (Exception e){
// notification without image in case of Exception
notificationManager.notify(id, notification);
}
}else{
notificationManager.notify(id, notification);
}
} catch (Exception e) {
e.printStackTrace();
}
}
**// main stuff goes here ,it is an inner class**
private Target target = new Target() {
@Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
if (bitmap != null) {
RemoteViews views;
views = new RemoteViews(getPackageName(), R.layout.custom_notification);
views.setTextViewText(R.id.title, "Daily Notification");
views.setTextColor(R.id.title,getResources().getColor(R.color.black));
views.setImageViewBitmap(R.id.big_picture, bitmap);
views.setImageViewBitmap(R.id.big_icon, BitmapFactory.decodeResource(getResources(), R.drawable.launcher_icon));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
notification.bigContentView = views;
}
}
}
@Override
public void onBitmapFailed(Drawable errorDrawable) {
Log.i("errorDrawable","errorDrawable");
}
@Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
};