码迷,mamicode.com
首页 > 其他好文 > 详细

关于SMS短信滞后阅读的实现方案

时间:2015-08-14 19:13:12      阅读:102      评论:0      收藏:0      [点我收藏+]

标签:onchange   contentobserver   registercontentobser   sms   

我大概描述下公司项目:公司App是进行手机联系人之间的加密电话,加密短信,加密密聊。

我大概描述下我接的一个任务:我是公司App的用户,并且在线,此刻其他App在线用户,用App的密信功能给我发了一条短信(注意不是手机系统短信发送的,而是App密信功能发来的),此刻我实时收到,因为我在线。

那么任务来了,我退出App,此刻对方再次给我发来一条SMS短信,任务要求是我登录App,能在密信列表收到在我退出App时候,对方给我发来的一条短信


SMSProcessor.instance.register();// 注册sms事件监听

	// 注册sms短信接收监听
	public void register() {

		context.getContentResolver().registerContentObserver(
				Uri.parse("content://sms/"), true, mAuthContentObserver);

		/** 从sp中获取保存的sms的Id值--上次App退出前,收到的最后一条短信id值 */
		SharedPreferencesUtils utils = new SharedPreferencesUtils(context,
				"lastSMSId");
		if (utils != null) {
			lasterId = utils.getlong("AppLastSMSId");
			// 或许>0判断的不严谨,不过我测试没问题,主要意思是如果App退出前存入的最后在线接收到的最后一条短信ID,那么sp里面获取的就是有值的,短信的id都是大于0的
			if (lasterId > 0) {
				// 如果>0,在进行判断,判断的条件会在方法里面说明
				insertSysSmsToLocalDatabase(lasterId);
			} else {
				// 这里貌似可有可无,因为测试没问题,我也懒得改了,因为我在后面的onChange方法里面有操作
				lasterId = getDefaultLasterId();
			}

		}
	}

	/**
	 * 这里进行获取是不是在app退出后,
	 */
	private void insertSysSmsToLocalDatabase(long AppLastSMSId) {
		// 查询系统的短信数据库,条件是判断是否大于上次App退出时候,保存的最后一条短信id,如果在此条件下,查询出来有结果集合,就说明,在我退出app时候,对方给我发来App密信
		List<IMessageDetail> smsDetails = SystemSms.querySMSById("_id > "
				+ AppLastSMSId);
		if (null == smsDetails || smsDetails.size() <= 0) {
			Log.e("AuthContentObserver", "null");
			return;
		}
		//这里是循环获取在我退出app时候,对方给我发来的App密信
		for (IMessageDetail smsDetail : smsDetails) {
			if (null != smsDetail) {
				String body = smsDetail.getMessageBody();
				String address = smsDetail.getMobileNum();
				// 打印不出来
				if (address.startsWith("+86"))
					address = address.substring(3);
				if (!TextUtils.isEmpty(body) && !TextUtils.isEmpty(address)) {
					//这些操作不用太理解,是获取系统短信的信息的,另外公司的app里面,还将系统内置的短信转为加密短信,下面应该是一系列操作
					byte[] bMsgs = body.getBytes();
					byte[] bAddress = address.getBytes();

					byte[] decMsg = SMSJNI.smsDecrpRequest(bMsgs, bMsgs.length,
							bAddress, bAddress.length);
					if (decMsg == null) { // 系统短信
						Log.e("AuthContentObserver", "decMsg:" + "is null");
					} else {
						String decContentString = new String(decMsg);
						smsDetail.setMessageBody(decContentString);
						smsDetail.setMobileNum(address);
						smsDetail
								.setMessageType(SQLiteManager.IMESSENGER_TYPE_SMS);
						smsDetail
								.setSendStatus(SQLiteManager.IMESSENGER_STATUS_SUCCEED);
						smsDetail.setContactId(0);
						//插入即可
						List<Long> IDList = SQLiteManager.getInstance()
								.insertIMessagebyMobile(smsDetail,
										smsDetail.getDirection());

						if (IDList == null || IDList.size() == 0)
							return;

						// 收到信息的广播--这里没有必要纠结,主要是用来做推送用的
						Intent intent = new Intent(Code.SMS_RECEIVED_ACTION);
						intent.putExtra("phoneNum", address);
						intent.putExtra("ISSRC", true);
						intent.putExtra("ID", IDList.get(0));
						// 发送广播
						context.sendBroadcast(intent);

						/**
						 * 在接受到退出app后,发来的短信后,需要更新lasterId值
						 */
						lasterId = getDefaultLasterId();
						/**
						 * 下面这操作也很重要,有人问这难道需要保存???
						 * 是的需要的,因为如果在app退出之后,收到对方app发来的密信,然后我直接关掉了,所以也得需要保存到sp中
						 */
						SharedPreferencesUtils spUtil = new SharedPreferencesUtils(
								context, "lastSMSId");
						// 存入sp文件中
						spUtil.setlong("AppLastSMSId", lasterId);
					}
				}
			}
		}

		// 发送广播

	}

/**
	 * 当短信uri发生变化时候,会调用onChange里面的方法
	 *当app在线时候,注意是在线时候,这里很重要,监听系统url变化
	 */
	private final class AuthContentObserver extends ContentObserver {
		public AuthContentObserver(Handler handler) {
			super(handler);
		}

		// 当所监听的Uri发生改变时,就会回调此方法
		@Override
		public void onChange(boolean selfChange) {
			super.onChange(selfChange);

			try {
				// 当app在线时候,注意是在线时候,这里很重要,监听系统url变化,这里还是lasterId,
				//我在每个阶段都赋值了,赋值的情况有1、退出app赋值2、登录app接受到新的密信赋值
				List<IMessageDetail> smsDetails = SystemSms
						.querySMSById("_id > " + lasterId);
				Log.e("AuthContentObserver", "lasterId:---+++" + lasterId);
				if (null == smsDetails || smsDetails.size() <= 0) {
					return;
				}
				//以下的操作跟上面讲的一样,差不多
				for (IMessageDetail smsDetail : smsDetails) {
					if (null != smsDetail) {
						String body = smsDetail.getMessageBody();
						String address = smsDetail.getMobileNum();

						if (address.startsWith("+86"))
							address = address.substring(3);

						if (!TextUtils.isEmpty(body)
								&& !TextUtils.isEmpty(address)) {
							byte[] bMsgs = body.getBytes();
							byte[] bAddress = address.getBytes();

							byte[] decMsg = SMSJNI.smsDecrpRequest(bMsgs,
									bMsgs.length, bAddress, bAddress.length);
							if (decMsg == null) { // 系统短信
								Log.e("AuthContentObserver", "decMsg:"
										+ "is null");
							} else {
								// 国鼎加密短信
								String decContentString = new String(decMsg);
								smsDetail.setMessageBody(decContentString);
								smsDetail.setMobileNum(address);
								smsDetail
										.setMessageType(SQLiteManager.IMESSENGER_TYPE_SMS);
								smsDetail
										.setSendStatus(SQLiteManager.IMESSENGER_STATUS_SUCCEED);
								smsDetail.setContactId(0);
								List<Long> IDList = SQLiteManager.getInstance()
										.insertIMessagebyMobile(smsDetail,
												smsDetail.getDirection());

								if (IDList == null || IDList.size() == 0)
									return;
								// 收到信息的广播
								Intent intent = new Intent(
										Code.SMS_RECEIVED_ACTION);
								intent.putExtra("phoneNum", address);
								intent.putExtra("ISSRC", true);
								intent.putExtra("ID", IDList.get(0));
								// 发送广播
								context.sendBroadcast(intent);
							}
						}
					}
					// 接受到消息后,重新赋值最新的信息id
					lasterId = smsDetail.getId();

					//以下操作就是在线时候,每次收到密信,就赋值
					SharedPreferencesUtils utils = new SharedPreferencesUtils(
							context, "lastSMSId");
					// 存入sp文件中
					utils.setlong("AppLastSMSId", lasterId);
				}

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

			}

		}
	}

	/**
	 * 从收信箱中获取最近的一条信息id
	 * 
	 * @return
	 */
	private long getDefaultLasterId() {
		Uri uri = Uri.parse("content://sms/inbox");
		String[] projection = new String[] { "body", "_id", "date" };
		Cursor cursor = null;
		try {
			cursor = context.getContentResolver().query(uri, projection, null,
					null, "_id DESC");

			if (cursor != null && cursor.getCount() > 0) {
				cursor.moveToFirst();
				long id = cursor.getLong(cursor.getColumnIndex(projection[1]));
				return id;
			}

		} catch (SQLException e) {
			Log.e("getDefaultLasterId", " " + e.toString());
		} finally {
			if (cursor != null) {
				cursor.close();
				cursor = null;
			}
		}
		return 0;
	}


版权声明:本文为博主原创文章,未经博主允许不得转载。

关于SMS短信滞后阅读的实现方案

标签:onchange   contentobserver   registercontentobser   sms   

原文地址:http://blog.csdn.net/u013210620/article/details/47664135

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!