You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android开发求助:如何用SQLite存储Bitmap与文本并展示到ListView

嘿,我来帮你搞定这个SQLite存储和ListView展示的问题!针对你用NotificationListenerService监听WhatsApp通知并存储到SQLite的需求,我先把完整的DatabaseHandler实现补全,再一步步讲清楚后续的检索、自定义Adapter和ListView绑定逻辑。


一、完整的DatabaseHandler实现

核心是把Bitmap转成字节数组(BLOB类型)存储,取出时再转回Bitmap。以下是完整代码:

public class DatabaseHandler extends SQLiteOpenHelper {
    // 数据库版本
    private static final int DATABASE_VERSION = 1;
    // 数据库名称
    private static final String DATABASE_NAME = "WhatsAppNotifications.db";
    // 表名
    private static final String TABLE_NOTIFICATIONS = "notifications";
    
    // 列名
    private static final String KEY_ID = "id";
    private static final String KEY_TEXT = "notification_text";
    private static final String KEY_ICON = "notification_icon";

    public DatabaseHandler(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    // 创建通知表
    @Override
    public void onCreate(SQLiteDatabase db) {
        String CREATE_TABLE = "CREATE TABLE " + TABLE_NOTIFICATIONS + "("
                + KEY_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
                + KEY_TEXT + " TEXT,"
                + KEY_ICON + " BLOB" + ")";
        db.execSQL(CREATE_TABLE);
    }

    // 数据库升级(简单处理:删旧表重建)
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_NOTIFICATIONS);
        onCreate(db);
    }

    // 添加一条通知数据
    public void addNotification(String text, Bitmap icon) {
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put(KEY_TEXT, text);
        
        // Bitmap转字节数组存储
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        icon.compress(Bitmap.CompressFormat.PNG, 100, stream);
        byte[] iconBytes = stream.toByteArray();
        values.put(KEY_ICON, iconBytes);
        
        db.insert(TABLE_NOTIFICATIONS, null, values);
        db.close();
    }

    // 获取所有通知数据
    public List<NotificationModel> getAllNotifications() {
        List<NotificationModel> notificationList = new ArrayList<>();
        String selectQuery = "SELECT * FROM " + TABLE_NOTIFICATIONS;
        
        SQLiteDatabase db = this.getReadableDatabase();
        Cursor cursor = db.rawQuery(selectQuery, null);
        
        // 遍历游标组装数据
        if (cursor.moveToFirst()) {
            do {
                NotificationModel notification = new NotificationModel();
                notification.setId(cursor.getInt(cursor.getColumnIndexOrThrow(KEY_ID)));
                notification.setText(cursor.getString(cursor.getColumnIndexOrThrow(KEY_TEXT)));
                
                // 字节数组转回Bitmap
                byte[] iconBytes = cursor.getBlob(cursor.getColumnIndexOrThrow(KEY_ICON));
                Bitmap icon = BitmapFactory.decodeByteArray(iconBytes, 0, iconBytes.length);
                notification.setIcon(icon);
                
                notificationList.add(notification);
            } while (cursor.moveToNext());
        }
        cursor.close();
        db.close();
        return notificationList;
    }
}

二、创建NotificationModel实体类

用来封装通知的文本和图标数据:

public class NotificationModel {
    private int id;
    private String text;
    private Bitmap icon;

    public NotificationModel() {}

    public NotificationModel(String text, Bitmap icon) {
        this.text = text;
        this.icon = icon;
    }

    // Getter & Setter
    public int getId() { return id; }
    public void setId(int id) { this.id = id; }

    public String getText() { return text; }
    public void setText(String text) { this.text = text; }

    public Bitmap getIcon() { return icon; }
    public void setIcon(Bitmap icon) { this.icon = icon; }
}

三、自定义ListView适配器(NotificationAdapter)

因为要同时展示图片和文本,需要自定义Adapter来适配布局:

public class NotificationAdapter extends ArrayAdapter<NotificationModel> {
    private Context context;
    private List<NotificationModel> notificationList;

    public NotificationAdapter(Context context, List<NotificationModel> notificationList) {
        super(context, R.layout.notification_list_item, notificationList);
        this.context = context;
        this.notificationList = notificationList;
    }

    @NonNull
    @Override
    public View getView(int position, View convertView, @NonNull ViewGroup parent) {
        View listItem = convertView;
        // 复用视图优化性能
        if (listItem == null) {
            listItem = LayoutInflater.from(context).inflate(R.layout.notification_list_item, parent, false);
        }

        NotificationModel currentItem = notificationList.get(position);
        
        // 绑定数据到视图
        ImageView iconView = listItem.findViewById(R.id.notification_icon);
        TextView textView = listItem.findViewById(R.id.notification_text);
        
        iconView.setImageBitmap(currentItem.getIcon());
        textView.setText(currentItem.getText());

        return listItem;
    }
}

对应的列表项布局res/layout/notification_list_item.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="16dp"
    android:orientation="horizontal"
    android:gravity="center_vertical">

    <ImageView
        android:id="@+id/notification_icon"
        android:layout_width="48dp"
        android:layout_height="48dp"
        android:marginEnd="16dp"/>

    <TextView
        android:id="@+id/notification_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="16sp"/>

</LinearLayout>

四、在Activity中绑定数据到ListView

在展示列表的Activity中,从数据库取数据并设置适配器:

public class NotificationListActivity extends AppCompatActivity {
    private ListView notificationListView;
    private DatabaseHandler dbHandler;
    private NotificationAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_notification_list);

        notificationListView = findViewById(R.id.notification_list);
        dbHandler = new DatabaseHandler(this);

        // 加载所有通知数据
        List<NotificationModel> notifications = dbHandler.getAllNotifications();
        
        // 设置适配器
        adapter = new NotificationAdapter(this, notifications);
        notificationListView.setAdapter(adapter);
    }

    // 有新通知时刷新列表的方法
    public void refreshList() {
        List<NotificationModel> updatedData = dbHandler.getAllNotifications();
        adapter.clear();
        adapter.addAll(updatedData);
        adapter.notifyDataSetChanged();
    }
}

对应的Activity布局res/layout/activity_notification_list.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ListView
        android:id="@+id/notification_list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>

五、在NotificationListenerService中存储通知

监听到WhatsApp通知时,提取文本和图标,调用addNotification方法存储:

public class WhatsAppNotificationListener extends NotificationListenerService {
    private DatabaseHandler dbHandler;

    @Override
    public void onCreate() {
        super.onCreate();
        dbHandler = new DatabaseHandler(this);
    }

    @Override
    public void onNotificationPosted(StatusBarNotification sbn) {
        super.onNotificationPosted(sbn);
        // 只处理WhatsApp的通知
        if ("com.whatsapp".equals(sbn.getPackageName())) {
            Notification notification = sbn.getNotification();
            // 提取通知文本
            String text = notification.extras.getString(Notification.EXTRA_TEXT, "");
            // 提取通知图标(优先取大图标)
            Bitmap icon = null;
            if (notification.getLargeIcon() != null) {
                icon = notification.getLargeIcon().loadDrawable(this).toBitmap();
            } else if (notification.getSmallIcon() != null) {
                icon = notification.getSmallIcon().loadDrawable(this).toBitmap();
            }
            
            if (icon != null && !text.isEmpty()) {
                dbHandler.addNotification(text, icon);
                // 可以通过广播/EventBus通知Activity刷新列表
                Intent intent = new Intent("com.your.package.NEW_NOTIFICATION");
                sendBroadcast(intent);
            }
        }
    }
}

六、Manifest配置要点

别忘了注册Service和添加必要权限:

<!-- 必要权限 -->
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY"/>

<application ...>
    <!-- 注册NotificationListenerService -->
    <service
        android:name=".WhatsAppNotificationListener"
        android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
        <intent-filter>
            <action android:name="android.service.notification.NotificationListenerService" />
        </intent-filter>
    </service>
</application>

内容的提问来源于stack exchange,提问作者PrincEVergil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:59:45