CursorLoader异步加载信鸽推送消息

Android SDK快速接入信鸽推送

信鸽平台注册应用:

  • 创建后, 查看配置获取AcessId和AcessKey信息
    这里写图片描述

工程配置

启动并注册APP或反注册

这里写图片描述

使用广播接收,并使用Notification通知到界面

public class MyXGPushReceiver extends XGPushBaseReceiver {

    private final static String TAG = "MyXGPushReceiver";
    private MediaPlayer mp;
    private UserPreference ps;
    private SimpleDateFormat mFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());


    @Override
    public void onRegisterResult(Context cntxt, int i,
                                 XGPushRegisterResult xgprr) {// 注册结果
    }

    @Override
    public void onUnregisterResult(Context cntxt, int i) {// 反注册结果
    }

    @Override
    public void onSetTagResult(Context cntxt, int i, String string) {
    }

    @Override
    public void onDeleteTagResult(Context cntxt, int i, String string) {
    }

    // 消息透传
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
    @Override
    public void onTextMessage(Context ctx, XGPushTextMessage msg) {
        String content = msg.getContent();
        String title=msg.getTitle();
        int msgType = -1;
        String url = "";
        long time = 0;
        try {
            JSONObject json = new JSONObject(msg.getCustomContent());
            msgType = Integer.parseInt(json.optString("msgType"));
            url = json.optString("url");
            Logger.d(msg.getContent() + "--" + msg.getCustomContent() + "--");
        } catch (Exception ex) {

        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA);
        // 保存到数据库
        XGMessage xgMsg = new XGMessage();
        xgMsg.content = content;
        xgMsg.msgType = msgType;
        xgMsg.url = url;
        xgMsg.time = sdf.format(time == 0 ? new Date() : new Date(time));
        xgMsg.isRead = 0; //未读
        xgMsg.title = title;

        XGMessageProviderHelper.getInstance(ctx).add(xgMsg);

        try {
            // 创建下拉通知
            Intent intent = new Intent();
            if (msgType == XGMessage.TYPE_NORMAL) {
                if (!TextUtils.isEmpty(url)) { //url地址直接打开网页
                    intent.setAction("android.intent.action.VIEW");
                    intent.addCategory("android.intent.category.DEFAULT");
                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    Uri uri = Uri.parse(url);
                    intent.setDataAndType(uri, "text/html");
                } else { //打开app
                    intent.setClass(ctx, MessageActivity.class);
                }
            }

            playKeyVoice();

            PendingIntent pi = PendingIntent.getActivity(ctx, 0, intent,
                    PendingIntent.FLAG_UPDATE_CURRENT);
            Notification.Builder builder = new Notification.Builder(ctx)
                    .setSmallIcon(R.mipmap.ic_launcher)//推送过来显示的图片
                    .setContentTitle(ctx.getString(R.string.app_name))//推送过来显示的文字
                    .setContentText(content)
                    .setWhen(time)
                    .setContentIntent(pi)
                    .setTicker("News is coming!");

            Notification notification = builder.build();
            notification.flags|= Notification.FLAG_AUTO_CANCEL;

            NotificationManager nm = (NotificationManager)ctx.getSystemService(NOTIFICATION_SERVICE);
            nm.notify((int)(time/1000), notification);

            Logger.d("onTextMessage ------->" + "创建消息通知");
        } catch (Exception e) {
            Logger.d("MyXGPushReceiver message:" + e.getMessage());
        }

    }
}

使用CursorLoader联合ContentProvider异步加载消息, 并展示在界面上

  • 消息推送关键在如何存储信息, 并及时更新显示在界面, 使用CursorLoader的好处,就是数据更新后,能通过监听自动更新显示在界面, 而不需要任务操作刷新等.
构建消息JavaBean:
public class XGMessage implements Parcelable{

    public static final int TYPE_ALARM = 1; //故障,滤网消息
    public static final int TYPE_NORMAL = 0; //普通消息

    public static final int UNREAD = 0;
    public static final int READ = 1;

    public int id; //消息id
    public int msgType; //消息类型. 0--链接(有url--打开网页, 没有url--打开app); 1-报警
    public String content; //消息内容
    public String url; //消息url
    public String time; //接收消息的时间
    public int isRead;  //是否已读。0-未读,1-已读
    public String title; //消息标题

    public XGMessage() {
    }

    protected XGMessage(Parcel in) {
        id = in.readInt();
        msgType = in.readInt();
        content = in.readString();
        url = in.readString();
        time = in.readString();
        isRead = in.readInt();
        title = in.readString();
    }

    public static final Creator<XGMessage> CREATOR = new Creator<XGMessage>() {
        @Override
        public XGMessage createFromParcel(Parcel in) {
            return new XGMessage(in);
        }

        @Override
        public XGMessage[] newArray(int size) {
            return new XGMessage[size];
        }
    };

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(id);
        dest.writeInt(msgType);
        dest.writeString(content);
        dest.writeString(url);
        dest.writeString(time);
        dest.writeInt(isRead);
        dest.writeString(title);
    }
}
编写契约类:
public class MessageConstract {

    public static final String CONTENT_AUTHORITY = "包名.provider";

    public static final Uri BASE_CONTENT_URI = Uri.parse("content://" + CONTENT_AUTHORITY);

    public static final String PATH_MESSAGE = "message";
    public static final String ITEM_MESSAGE = "message/#";

    public static final String BASE_CONTENT_TYPE = "sumeida";


    /**
     * @see  <herf>https://www.sitepoint.com/create-your-own-content-provider-in-android/</herf>
     */
    public static final class Messages implements BaseColumns {

        public static final Uri CONTENT_URI = BASE_CONTENT_URI.buildUpon().
                appendPath(PATH_MESSAGE).build();

        public static final String CONTENT_ITEM_TYPE =
                ContentResolver.CURSOR_ITEM_BASE_TYPE + "/" + "vnd." + BASE_CONTENT_TYPE + "." + PATH_MESSAGE;


        /**
         * We will start by implementing the getType method. The getType method returns the Mime type of the data as a string.
         * The returned mime type should be in the format vnd.<uri pattern>./vnd.<name>.<type>.
         * Where the <uri pattern> for a single row should be android.cursor.item, for multiple rows android.cursor.dir
         * and the <name> should be globally unique (use the package name). <type> should be unique to the corresponding URI.
         */
        public static String CONTENT_TYPE =
                ContentResolver.CURSOR_DIR_BASE_TYPE + "/" + "vnd." + BASE_CONTENT_TYPE + "." + PATH_MESSAGE;


        /*表名*/
        public static final String TABLE_NAME = "message_list";
        /*用户名*/
        public static final String COLUMN_MESSAGE_USER = "username";
        /*消息内容*/
        public static final String COLUMN_MESSAGE_CONTENT = "content";
        /*消息标题*/
        public static final String COLUMN_MESSAGE_TITLE = "title";
        /*消息类型*/
        public static final String COLUMN_MESSAGE_TYPE = "msgType";
        /*消息URL*/
        public static final String COLUMN_MESSAGE_URL = "url";
        /*消息时间*/
        public static final String COLUMN_MESSAGE_TIME = "time";
        /*消息是否阅读*/
        public static final String COLUMN_MESSAGE_READ = "isRead";



        public static Uri buildMessageUri(long id) {
            return ContentUris.withAppendedId(CONTENT_URI, id);
        }

    }
构建SqliteHelper:
public class XGMessageDBHelper extends SQLiteOpenHelper {

    private static final String DB_NAME = "sumeida_mower.db";
    private volatile static XGMessageDBHelper sHelper;
    private static final int DB_VERSION = 1;

    private XGMessageDBHelper(Context context) {
        super(context, DB_NAME, null, DB_VERSION);
    }

    public static XGMessageDBHelper getInstance(Context context) {
        if (sHelper == null) {
            synchronized (XGMessageDBHelper.class) {
                if (sHelper == null) {
                    sHelper = new XGMessageDBHelper(context);
                }
            }
        }
        return sHelper;
    }

    //信息--id,msgType,content,url,receiveTime, isRead,mac
    @Override
    public void onCreate(SQLiteDatabase db) {
        final String SQL_CREATE_MESSAGE_TABLE=
                "CREATE TABLE "+ TABLE_NAME +"("
                + _ID+" INTEGER PRIMARY KEY AUTOINCREMENT, "
                + COLUMN_MESSAGE_TITLE+" TEXT,"
                + COLUMN_MESSAGE_CONTENT+" TEXT, "
                + COLUMN_MESSAGE_TIME+" TEXT, "
                + COLUMN_MESSAGE_URL+" TEXT, "
                + COLUMN_MESSAGE_TYPE+" INTEGER DEFAULT -1, "
                + COLUMN_MESSAGE_READ+" INTEGER DEFAULT 0, "
                + COLUMN_MESSAGE_USER+" TEXT NOT NULL"
                +")";

        db.execSQL(SQL_CREATE_MESSAGE_TABLE);
    }


    //升级
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

        db.execSQL("DROP TABLE IF EXITS "+ MessageConstract.Messages.TABLE_NAME);

        onCreate(db);
    }

    //表降级
    @Override
    public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        super.onDowngrade(db, oldVersion, newVersion);
    }
}
构建内容提供者:
public class XGMessageProvider extends ContentProvider {

    private static final int MSG_ALL = 0;
    private static final int MSG_ONE = 1; //单条消息
    private static UriMatcher sMatcher;

    static {
        sMatcher = new UriMatcher(UriMatcher.NO_MATCH);

        sMatcher.addURI(MessageConstract.CONTENT_AUTHORITY, MessageConstract.PATH_MESSAGE, MSG_ALL);
        sMatcher.addURI(MessageConstract.CONTENT_AUTHORITY, MessageConstract.ITEM_MESSAGE, MSG_ONE);
    }

    private XGMessageDBHelper mHelper;
    private SQLiteDatabase mDb;

    @Override
    public boolean onCreate() {

        mHelper = XGMessageDBHelper.getInstance(getContext());

        return true;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {

        int match = sMatcher.match(uri);
        Cursor cursor;
        mDb = mHelper.getReadableDatabase();
        switch (match) {
            case MSG_ALL:
                cursor = mDb.query(Messages.TABLE_NAME,
                        projection,
                        selection,
                        selectionArgs,
                        null,
                        null,
                        sortOrder);
                break;
            case MSG_ONE:
                cursor = mDb.query(Messages.TABLE_NAME,
                        projection,
                        Messages._ID + " LIKE ?",
                        new String[]{String.valueOf(uri.getLastPathSegment())},
                        null,
                        null,
                        sortOrder);
                break;
            default:
                throw new IllegalArgumentException("Wrong URI: " + uri);
        }

        cursor.setNotificationUri(getContext().getContentResolver(), uri);

        return cursor;
    }


    @Override
    public Uri insert(Uri uri, ContentValues values) {
        int match = sMatcher.match(uri);
        mDb= mHelper.getWritableDatabase();
        Uri itemUri = null;
        long rowId;
        switch (match){
            case MSG_ALL:
                rowId = mDb.insert(Messages.TABLE_NAME, null, values);
                if(rowId > 0){
                    itemUri = Messages.buildMessageUri(rowId);
                }else if(rowId == -1){
                    throw new SQLiteException("Failed to insert values into table message.");
                }
                break;
            default:
                throw new IllegalArgumentException("Wrong URI: "+uri);
        }
        getContext().getContentResolver().notifyChange(uri, null);
        return itemUri;

    }


    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {

        int match = sMatcher.match(uri);
        mDb= mHelper.getWritableDatabase();
        int rowId;
        switch (match) {
            case MSG_ALL:
                rowId= mDb.delete(Messages.TABLE_NAME, selection, selectionArgs);
                break;
            case MSG_ONE:

                rowId= mDb.delete(Messages.TABLE_NAME,
                        Messages._ID+" LIKE ?",
                        new String[]{uri.getLastPathSegment()});
                break;
            default:
                throw new IllegalArgumentException("Wrong URI: " + uri);
        }

        if (rowId < 0) {
            throw new SQLiteException("Failed to delete message!");
        }

        getContext().getContentResolver().notifyChange(uri, null);

        return rowId;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        int match = sMatcher.match(uri);
        mDb= mHelper.getWritableDatabase();
        int rowId ;
        switch (match) {
            case MSG_ALL:
                rowId = mDb.update(Messages.TABLE_NAME, values, selection, selectionArgs);
                break;
            case MSG_ONE:
                String id = uri.getLastPathSegment();
                if (TextUtils.isEmpty(selection)) {
                    rowId = mDb.update(Messages.TABLE_NAME,
                            values,
                            Messages._ID + "=" + id,
                            null);
                } else {
                    rowId = mDb.update(Messages.TABLE_NAME,
                            values,
                            Messages._ID + "=" + id
                            +" AND "+ selection,
                            selectionArgs);
                }
                break;
            default:
                throw new IllegalArgumentException("Wrong URI: " + uri);
        }

        if (rowId < 0) {
            throw new SQLiteException("Failed to update the Message ");
        }

        getContext().getContentResolver().notifyChange(uri, null);

        return rowId;
    }


    @Override
    public String getType(Uri uri) {
        int match = sMatcher.match(uri);

        String type;
        switch (match){
            case MSG_ALL:
                type= Messages.CONTENT_TYPE;
                break;
            case MSG_ONE:
                type= Messages.CONTENT_ITEM_TYPE;
                break;
            default:
                throw new IllegalArgumentException("Wrong URI:"+uri);
        }
        return type;
    }
    @Override
    public int bulkInsert(Uri uri, ContentValues[] values) {
        mDb= mHelper.getWritableDatabase();
        int rtnCount = 0;
        switch (sMatcher.match(uri)){
            case MSG_ALL:
                mDb.beginTransaction();
                try{
                    for(ContentValues value : values){
                        long id = mDb.insert(Messages.TABLE_NAME, null, value);
                        if(id != -1){
                            rtnCount++;
                        }
                    }
                    mDb.setTransactionSuccessful();
                    getContext().getContentResolver().notifyChange(uri, null);
                    return rtnCount;

                }finally {
                    mDb.endTransaction();
                }

            default:
                break;
        }

        return super.bulkInsert(uri, values);
    }

}
构建ProviderHelper类,使用contentResovler操作数据库:
public class XGMessageProviderHelper {

    public static volatile XGMessageProviderHelper sProviderHelper;
    private final Context context;
    private XGMessageDBHelper mHelper;
    private UserPreference up;

    private XGMessageProviderHelper(Context context) {
        this.context = context;
        mHelper = XGMessageDBHelper.getInstance(context);
        up = UserPreference.getInstance();
    }

    public static XGMessageProviderHelper getInstance(Context context) {
        if (sProviderHelper == null) {
            synchronized (XGMessageProviderHelper.class) {
                if (sProviderHelper == null) {
                    sProviderHelper = new XGMessageProviderHelper(context);
                }
            }
        }
        return sProviderHelper;
    }


    /**
     * 添加消息到数据库中
     *
     * @param msg 信息
     * @return true--添加成功
     */
    public Uri add(XGMessage msg) {
        ContentValues values = new ContentValues();
        values.put(COLUMN_MESSAGE_USER, up.getUsername());
        values.put(COLUMN_MESSAGE_TYPE, msg.msgType);
        values.put(COLUMN_MESSAGE_CONTENT, msg.content);
        values.put(COLUMN_MESSAGE_URL, msg.url);
        values.put(COLUMN_MESSAGE_TIME, msg.time);
        values.put(COLUMN_MESSAGE_READ, msg.isRead);
        values.put(COLUMN_MESSAGE_TITLE, msg.title);
        return context.getContentResolver().insert(CONTENT_URI, values);
    }

    public int updateMessageRead(int id) {
        String whereClause = _ID + " LIKE ?";
        String[] selectionArgs = new String[]{String.valueOf(id)};
        ContentValues values = new ContentValues();
        values.put(COLUMN_MESSAGE_READ, XGMessage.READ);
        return context.getContentResolver().update(CONTENT_URI, values, whereClause, selectionArgs);
    }

    /**
     * 根据ID和用户名删除信息
     *
     * @param id 信息
     * @return -1 rows failed
     */
    public int delete(int id) {

        String where = _ID + " LIKE ?" + " AND " + COLUMN_MESSAGE_USER + " LIKE ? ";
        String[] selectionArgs = new String[]{String.valueOf(id), up.getUsername()};
        return context.getContentResolver().delete(CONTENT_URI, where, selectionArgs);
    }


    /**
     * 判断表中是否已经含有消息
     * <p/>
     * param 消息
     *
     * @return true 表示表中有数据
     */
    public boolean hasMessage(int id) {

        String selections = _ID + "Like ?";

        String selectionArgs[] = new String[]{String.valueOf(id)};

        Cursor cursor = context.getContentResolver().query(CONTENT_URI,
                null, selections, selectionArgs, null);
        if (cursor != null) {
            cursor.close();
            return true;
        }
        return false;

    }

    /**
     * 获取所有的消息
     *
     * @return
     */
    public XGMessage queryMessage(int id) {

        String selections = COLUMN_MESSAGE_USER + " LIKE ?" + " AND " + _ID + " LIKE ?";

        String selectionArgs[] = new String[]{up.getUsername(), String.valueOf(id)};

        Cursor cursor = context.getContentResolver().query(CONTENT_URI,
                null, selections, selectionArgs, null);
        try {
            if (cursor != null && cursor.moveToFirst()) {
                return dumpCursorToXMessage(cursor);
            }
        }finally {
            if (cursor!=null){
                cursor.close();
            }
        }
        return null;
    }


    public XGMessage dumpCursorToXMessage(Cursor cursor){

        XGMessage message=null;
        if (!cursor.isAfterLast()&& !cursor.isBeforeFirst()){
            message= new XGMessage();
            message.id= cursor.getInt(cursor.getColumnIndex(Messages._ID));
            message.title= cursor.getString(cursor.getColumnIndex(Messages.COLUMN_MESSAGE_TITLE));
            message.content= cursor.getString(cursor.getColumnIndex(Messages.COLUMN_MESSAGE_CONTENT));
            message.url= cursor.getString(cursor.getColumnIndex(Messages.COLUMN_MESSAGE_URL));
            message.msgType= cursor.getInt(cursor.getColumnIndex(Messages.COLUMN_MESSAGE_TYPE));
            message.time= cursor.getString(cursor.getColumnIndex(Messages.COLUMN_MESSAGE_TIME));
            message.isRead= cursor.getInt(cursor.getColumnIndex(Messages.COLUMN_MESSAGE_READ));
        }
        return message;
    }
}

一切完善后,构建消息显示界面, 使用CursorLoader异步加载数据:

public class MessageActivity extends BaseActivity implements AdapterView.OnItemClickListener,
        SwipeRefreshLayout.OnRefreshListener, AdapterView.OnItemLongClickListener {
    public static final String MESSAGE = "message";
    private static final int MESSAGE_LOAD = 1;
    private SwipeRefreshLayout mSwipeRefreshLayout;
    private ListView mListView;
    private TextView mTvNoMessage;
    private CursorAdapter mAdapter;

    @Override
    protected int getLayoutResId() {
        return R.layout.activity_message;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setTitle("Message");
        initView();
        initData();
        initEvent();
    }

    private void initView() {
        mListView = (ListView) findViewById(R.id.message_lv);
        mTvNoMessage = (TextView) findViewById(R.id.message_tv_no_message);

    }

    private void initData() {

        mListView.setEmptyView(mTvNoMessage);

        initLoader();

        setCursorAdapter();
    }


    private void initLoader() {
        getSupportLoaderManager().initLoader(MESSAGE_LOAD, null, new LoaderCallbacks<Cursor>() {
            @Override
            public Loader<Cursor> onCreateLoader(int id, Bundle args) {

                String sortOrder = Messages.TABLE_NAME + "." + Messages._ID + " DESC ";
                return new CursorLoader(MessageActivity.this,
                        Messages.CONTENT_URI,
                        null,
                        Messages.COLUMN_MESSAGE_USER + " LIKE ?",
                        new String[]{UserPreference.getInstance().getUsername()},
                        sortOrder);
            }

            @Override
            public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
                if (loader.getId() == MESSAGE_LOAD) {
                    mAdapter.swapCursor(data);
                }
            }

            @Override
            public void onLoaderReset(Loader<Cursor> loader) {
                mAdapter.swapCursor(null);
            }
        });

    }

    private void setCursorAdapter() {

        mAdapter = new CursorAdapter(this, null, false) {
            @Override
            public View newView(Context context, Cursor cursor, ViewGroup parent) {
                View view = View.inflate(context, R.layout.item_message, null);
                ViewHolder holder = new ViewHolder(view);
                view.setTag(holder);
                return view;
            }

            @Override
            public void bindView(View view, Context context, Cursor cursor) {
                ViewHolder holder = (ViewHolder) view.getTag();
                holder.content.setText(cursor.getString(cursor.getColumnIndex(Messages.COLUMN_MESSAGE_CONTENT)));
                holder.title.setText(cursor.getString(cursor.getColumnIndex(Messages.COLUMN_MESSAGE_TITLE)));
                holder.date.setText(cursor.getString(cursor.getColumnIndex(Messages.COLUMN_MESSAGE_TIME)));

                holder.indicator.setVisibility(cursor.getInt(cursor.getColumnIndex(Messages.COLUMN_MESSAGE_READ))
                        == XGMessage.READ ? View.INVISIBLE : View.VISIBLE);

            }
        };

        mListView.setAdapter(mAdapter);
    }

    private void initEvent() {
        mListView.setOnItemClickListener(this);
        mListView.setOnItemLongClickListener(this);

    }

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        Cursor cursor = (Cursor) parent.getItemAtPosition(position);
        // 将消息更新为已读
        XGMessageProviderHelper.getInstance(this).updateMessageRead((int) id);
        //使用cursor获取到当前位置的message对象
        XGMessage message = XGMessageProviderHelper.getInstance(this).dumpCursorToXMessage(cursor);
        Intent intent = new Intent(this, MessageDetailActivity.class);
        intent.putExtra(MESSAGE, message);
        startActivity(intent);
    }

    @Override
    public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
        AlertDialogManager.deleteMessage(this, (int) id);
        return true;
    }

    class ViewHolder {
        TextView title;
        TextView date;
        TextView content;
        View indicator;

        public ViewHolder(View view) {
            content = (TextView) view.findViewById(R.id.message_tv_content);
            title = (TextView) view.findViewById(R.id.message_tv_title);
            date = (TextView) view.findViewById(R.id.message_tv_data);
            indicator = view.findViewById(R.id.message_indicator);
        }
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值