在通知 Android 中从 url 加载图像

在我的 android 应用程序中,我想动态地设置通知图标,这些图标将从 URL 加载。为此,我在 receiver中使用了 NotificationBuilder 的 setLargeIcon属性。我引用了许多链接,尝试了各种解决方案,但是没有得到想要的输出。虽然我从网址下载了那个图像,并在通知中设置了那个位图,但是它并没有显示出来。相反,它将 setSmallIcon图像显示为大图标。我不知道我哪里做错了。在这里我张贴我的代码。请帮我解决这个问题。谢谢你。

密码:

@SuppressLint("NewApi")
public class C2DMMessageReceiver extends BroadcastReceiver {


@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if ("com.google.android.c2dm.intent.RECEIVE".equals(action)) {
Log.e("C2DM", "received message");
final String fullName = intent.getStringExtra("message");
final String payload1 = intent.getStringExtra("message1");
final String payload2 = intent.getStringExtra("message2");
final String userImage = intent.getStringExtra("userImage");


Log.e("userImage Url :", userImage); //it shows correct url


new sendNotification(context)
.execute(fullName, payload1, userImage);
}
}


private class sendNotification extends AsyncTask<String, Void, Bitmap> {


Context ctx;
String message;


public sendNotification(Context context) {
super();
this.ctx = context;
}


@Override
protected Bitmap doInBackground(String... params) {


InputStream in;
message = params[0] + params[1];
try {


in = new URL(params[2]).openStream();
Bitmap bmp = BitmapFactory.decodeStream(in);
return bmp;


} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}


@Override
protected void onPostExecute(Bitmap result) {


super.onPostExecute(result);
try {
NotificationManager notificationManager = (NotificationManager) ctx
.getSystemService(Context.NOTIFICATION_SERVICE);


Intent intent = new Intent(ctx, NotificationsActivity.class);
intent.putExtra("isFromBadge", false);




Notification notification = new Notification.Builder(ctx)
.setContentTitle(
ctx.getResources().getString(R.string.app_name))
.setContentText(message)
.setSmallIcon(R.drawable.ic_launcher)
.setLargeIcon(result).build();


// hide the notification after its selected
notification.flags |= Notification.FLAG_AUTO_CANCEL;


notificationManager.notify(1, notification);


} catch (Exception e) {
e.printStackTrace();
}
}
}
85661 次浏览

修改了下面的代码,现在可以工作了:

private class sendNotification extends AsyncTask<String, Void, Bitmap> {


Context ctx;
String message;


public sendNotification(Context context) {
super();
this.ctx = context;
}


@Override
protected Bitmap doInBackground(String... params) {


InputStream in;
message = params[0] + params[1];
try {


URL url = new URL(params[2]);
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setDoInput(true);
connection.connect();
in = connection.getInputStream();
Bitmap myBitmap = BitmapFactory.decodeStream(in);
return myBitmap;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}


@Override
protected void onPostExecute(Bitmap result) {


super.onPostExecute(result);
try {
NotificationManager notificationManager = (NotificationManager) ctx
.getSystemService(Context.NOTIFICATION_SERVICE);


Intent intent = new Intent(ctx, NotificationsActivity.class);
intent.putExtra("isFromBadge", false);




Notification notification = new Notification.Builder(ctx)
.setContentTitle(
ctx.getResources().getString(R.string.app_name))
.setContentText(message)
.setSmallIcon(R.drawable.ic_launcher)
.setLargeIcon(result).build();


// hide the notification after its selected
notification.flags |= Notification.FLAG_AUTO_CANCEL;


notificationManager.notify(1, notification);


} catch (Exception e) {
e.printStackTrace();
}
}
}

如何实现 大图片风格通知:

.setStyle(new Notification.BigPictureStyle().bigPicture(result))创造了奇迹:

我已经这样做了:

enter image description here

AsyncTask生成通知 :

new generatePictureStyleNotification(this,"Title", "Message",
"http://api.androidhive.info/images/sample.jpg").execute();

AsyncTask :

public class generatePictureStyleNotification extends AsyncTask<String, Void, Bitmap> {


private Context mContext;
private String title, message, imageUrl;


public generatePictureStyleNotification(Context context, String title, String message, String imageUrl) {
super();
this.mContext = context;
this.title = title;
this.message = message;
this.imageUrl = imageUrl;
}


@Override
protected Bitmap doInBackground(String... params) {


InputStream in;
try {
URL url = new URL(this.imageUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
in = connection.getInputStream();
Bitmap myBitmap = BitmapFactory.decodeStream(in);
return myBitmap;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}


@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
@Override
protected void onPostExecute(Bitmap result) {
super.onPostExecute(result);


Intent intent = new Intent(mContext, MyOpenableActivity.class);
intent.putExtra("key", "value");
PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 100, intent, PendingIntent.FLAG_ONE_SHOT);


NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notif = new Notification.Builder(mContext)
.setContentIntent(pendingIntent)
.setContentTitle(title)
.setContentText(message)
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(result)
.setStyle(new Notification.BigPictureStyle().bigPicture(result))
.build();
notif.flags |= Notification.FLAG_AUTO_CANCEL;
notificationManager.notify(1, notif);
}
}

我知道已经给出了一个很好的答案,所以让我们看看我们是否可以使它更容易理解和执行。
——————————理论——————————
这个问题可以抽象为两步解
1)从 URL 获取图像
2)解码图像并传递给通知生成器

1)从 URL 获取图像
InputStream in = new URL("Img URL goes here eg. http://gg.com/profile.jpg").openStream();

2)解码并传送至通知
Bitmap bmp = null; # 创建一个空 bmp 容器,用于保存解码后的 img
bmp = BitmapFactory.decodeStream(in); # 将图像保存到容器中

瞧! 一旦构建了映像并将其保存到变量 bmp 中,就可以在通知构建器上调用它 .setLargeIcon(bmp) < br > < br > ————实施————————
Android 工作室将鼓励您用 try catch 包装代码,以便最终产品看起来像这样。

Bitmap bmp = null;
try {
InputStream in = new URL("url goes here").openStream();
bmp = BitmapFactory.decodeStream(in);
} catch (IOException e) {
e.printStackTrace();
}

一旦你有了 bmp,你可以在通知生成器中调用它

NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_launcher)
.setContentText("title")
.setContentText("text goes here")
.setLargeIcon(bmp)
.setAutoCancel(true);

你可以这样使用 Glide:

val notificationBuilder = NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.drawable.ic_message)
.setContentTitle("title")
.setContentText("text")


val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager


val futureTarget = Glide.with(this)
.asBitmap()
.load(photoUrl)
.submit()


val bitmap = futureTarget.get()
notificationBuilder.setLargeIcon(bitmap)


Glide.with(this).clear(futureTarget)


notificationManager.notify(0, notificationBuilder.build())

preview

使用毕加索图书馆。

               Target target = new Target() {
@Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
largeIcon=bitmap;
}


@Override
public void onBitmapFailed(Drawable errorDrawable) {
}


@Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
};


Picasso.with(this).load("url").into(target);










NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.drawable.icon)
.setContentTitle(msg.getString("title"))
.setContentText(msg.getString("msg"))
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setLargeIcon(largeIcon)
.setContentIntent(pendingIntent);

Kotlin 顶级答案和 Coroutines。此方法将位图应用于 builder,而不是直接赋值,当然,如果位图可用的话。这很好,因为如果 url 错误,它将在 try/catch 中被捕获。

fun applyImageUrl(
builder: NotificationCompat.Builder,
imageUrl: String
) = runBlocking {
val url = URL(imageUrl)


withContext(Dispatchers.IO) {
try {
val input = url.openStream()
BitmapFactory.decodeStream(input)
} catch (e: IOException) {
null
}
}?.let { bitmap ->
builder.setLargeIcon(bitmap)
}
}

和 Kotlin & RxJava 合作

fun applyImageUrl(
builder: NotificationCompat.Builder,
imageUrl: String
) {
val url = URL(imageUrl)


Single.create<Bitmap> { emitter ->
try {
val input = url.openStream()
val bitmap = BitmapFactory.decodeStream(input)
emitter.onSuccess(bitmap)
} catch (e: Exception) {
emitter.onError(e)
}
}.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{
builder.setLargeIcon(it)
}, {
Timber.e("error generating bitmap for notification")
}
)
}

因为图像是从互联网上加载的,所以它应该在一个背景线程中完成 异步。要么使用异步任务,要么使用 Glide (用于高效的图像加载)。

要加载图像通知,需要使用“ NotificationCompat。BigPictureStyle ()”。这需要一个 位图(必须从图像 URL 中提取)

现在,滑行的大多数 API 和方法都不再推荐使用。 下面是使用 Glide 4.9和 Android 10的工作流程。

 // Load bitmap from image url on background thread and display image notification
private void getBitmapAsyncAndDoWork(String imageUrl) {


final Bitmap[] bitmap = {null};


Glide.with(getApplicationContext())
.asBitmap()
.load(imageUrl)
.into(new CustomTarget<Bitmap>() {
@Override
public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {


bitmap[0] = resource;
// TODO Do some work: pass this bitmap
displayImageNotification(bitmap[0]);
}


@Override
public void onLoadCleared(@Nullable Drawable placeholder) {
}
});
}

显示图像通知一次,位图就准备好了。

private void displayImageNotification(Bitmap bitmap) {


NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext(), getChannelId());
builder
.setContentTitle(title)
.setContentText(subtext)
.setDefaults(Notification.DEFAULT_LIGHTS | Notification.DEFAULT_VIBRATE)
.setSmallIcon(SMALL_ICON)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setColor(getApplicationContext().getColor(color))
.setAutoCancel(true)
.setOngoing(false)
.setOnlyAlertOnce(true)
.setContentIntent(pendingIntent)
.setStyle(
new NotificationCompat.BigPictureStyle().bigPicture(bitmap))
.setPriority(Notification.PRIORITY_HIGH);


getManager().notify(tag, id, builder.build());
}

因为我不能找到任何工作的解决方案,毕加索我张贴我的完整和工作(2020年7月)的例子使用毕加索下面。

它会立即发送通知,然后在加载 setLargeIcon ()的映像时进行更新。通常,这是非常快的,用户应该只看到通知的更新版本在大多数情况下。

private void sendNotification(String message, String title, final String photoUrl) {
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent,
PendingIntent.FLAG_ONE_SHOT);


final NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.wbib_transp_512)
.setContentTitle(title)
.setContentText(message)
.setAutoCancel(true)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setCategory(NotificationCompat.CATEGORY_MESSAGE)
.setContentIntent(pendingIntent);


final NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);


notificationManager.notify(0, notificationBuilder.build());


final Handler uiHandler = new Handler(Looper.getMainLooper());
uiHandler.post(new Runnable() {
@Override
public void run() {
Picasso.get()
.load(photoUrl)
.resize(200, 200)
.into(new Target() {
@Override
public void onBitmapLoaded(final Bitmap bitmap, final Picasso.LoadedFrom from) {
notificationBuilder.setLargeIcon(bitmap);
notificationManager.notify(0, notificationBuilder.build());
}


@Override
public void onBitmapFailed(Exception e, final Drawable errorDrawable) {
// Do nothing?
}


@Override
public void onPrepareLoad(final Drawable placeHolderDrawable) {
// Do nothing?
}
});
}
});




}

RxJava 和毕加索的方式

private fun bigImageNotification(ctx: Context, title: String, msg: String, imgUrl: String): Disposable? {
return Observable.fromCallable {
Picasso.get().load(imgUrl).get()
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
createNotification(ctx, title, msg, it)
}, {it.printStackTrace()})
}


private fun createNotification(ctx: Context, title: String, msg: String, img: Bitmap?) {
val b = Notification.Builder(ctx)
b.setAutoCancel(true)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(title)
.setContentText(msg)
.setStyle(Notification.BigPictureStyle().bigPicture(img))
val notificationManager = ctx.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.notify(1000, b.build())
}

用法

bigImageNotification(context, "title", "msg", "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png")