Java tutorial
/* Copyright 2012-2013, Polyvi Inc. (http://polyvi.github.io/openxface) This program is distributed under the terms of the GNU General Public License. This file is part of xFace. xFace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. xFace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with xFace. If not, see <http://www.gnu.org/licenses/>. */ package com.polyvi.xface.extension; import java.security.InvalidParameterException; import java.util.ArrayList; import java.util.Iterator; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import android.app.Activity; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.database.Cursor; import android.database.sqlite.SQLiteException; import android.net.Uri; import android.os.Bundle; import android.provider.BaseColumns; import android.telephony.SmsManager; import android.telephony.SmsMessage; import com.polyvi.xface.event.XEvent; import com.polyvi.xface.event.XEventType; import com.polyvi.xface.event.XSystemEventCenter; import com.polyvi.xface.extension.XExtensionResult.Status; import com.polyvi.xface.plugin.api.XIWebContext; import com.polyvi.xface.util.XUtils; public class XMessagingExt extends XExtension { private static final Uri mSMSContentUri = Uri.parse("content://sms/"); private static final String FOLDERTYPE_DRAFT = "draft"; private static final String MESSAGE_TYPE_SMS = "SMS"; private static final String MESSAGE_TYPE_MMS = "MMS"; private static final String MESSAGE_TYPE_EMAIL = "Email"; private static final String COMMAND_SENDMESSAGE = "sendMessage"; private static final String COMMAND_GETQUANTITIES = "getQuantities"; private static final String COMMAND_GETMESSAGE = "getMessage"; private static final String COMMAND_GETALLMESSAGES = "getAllMessages"; private static final String COMMAND_FINDMESSAGES = "findMessages"; private static final String SMS_SENT = "SMS_SENT"; private static final String INTENT_ACTION = "android.provider.Telephony.SMS_RECEIVED"; /**< Intentaction??action*/ private BroadcastReceiver mSendSMSBroadcastReceiver = null; private BroadcastReceiver mMsgReceiveBroadcaseReveiver = null; private XCallbackContext mCallbackCtx; private enum SMS_RESULT_STATUS { SEND_SUCCESS, //??? ERROR_GENERIC_FAILURE, // ERROR_NO_SERVICE, //? ERROR_NULL_PDU, //PDU?? ERROR_RADIO_OFF, // NO_STATUS //?native??? } @Override public void sendAsyncResult(String result) { } @Override public boolean isAsync(String action) { return true; } @Override public void init(XExtensionContext extensionContext, XIWebContext webContext) { super.init(extensionContext, webContext); genMsgReceiveBroadcastReceive(); regMsgReceiver(); } private void genMsgReceiveBroadcastReceive() { if (null == mMsgReceiveBroadcaseReveiver) { mMsgReceiveBroadcaseReveiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (INTENT_ACTION.equals(intent.getAction())) { Bundle bundle = intent.getExtras(); if (null != bundle) { // pdus?? Object[] pdus = (Object[]) bundle.get("pdus"); // SmsMessage[] msgs = new SmsMessage[pdus.length]; for (int i = 0; i < pdus.length; i++) { // ???pdu?,? msgs[i] = SmsMessage.createFromPdu((byte[]) pdus[i]); } JSONArray receivedMsgs = buildSmsList(msgs); XEvent evt = XEvent.createEvent(XEventType.MSG_RECEIVED, receivedMsgs.toString()); XSystemEventCenter.getInstance().sendEventAsync(evt); } } } }; } } /** * * */ private JSONArray buildSmsList(SmsMessage[] msgs) { JSONArray smsList = new JSONArray(); for (SmsMessage msg : msgs) { try { JSONObject msgJsonObj = buildSmsJsonObj(msg); smsList.put(msgJsonObj); } catch (JSONException e) { e.printStackTrace(); } } return smsList; } /** * ?json * */ private JSONObject buildSmsJsonObj(SmsMessage msg) throws JSONException { JSONObject msgJsonObj = new JSONObject(); msgJsonObj.put("msgId", ""); msgJsonObj.put("subject", msg.getPseudoSubject()); msgJsonObj.put("body", msg.getDisplayMessageBody()); msgJsonObj.put("destinationAddresses", ""); msgJsonObj.put("originatingAddress", msg.getDisplayOriginatingAddress()); msgJsonObj.put("messageType", "SMS"); boolean isRead = false; if (SmsManager.STATUS_ON_ICC_READ == msg.getStatusOnIcc()) { isRead = true; } msgJsonObj.put("isRead", isRead); msgJsonObj.put("date", msg.getTimestampMillis()); return msgJsonObj; } private void regMsgReceiver() { getContext().registerReceiver(mMsgReceiveBroadcaseReveiver, new IntentFilter(INTENT_ACTION)); } @Override public XExtensionResult exec(String action, JSONArray args, XCallbackContext callbackCtx) throws JSONException { XExtensionResult.Status status = XExtensionResult.Status.OK; String result = ""; mCallbackCtx = callbackCtx; try { if (action.equals(COMMAND_SENDMESSAGE)) { return sendMessage(mWebContext, args.getString(0), args.getString(1), args.getString(2), args.getString(3)); } else if (action.equals(COMMAND_GETQUANTITIES)) { int numbers = getQuantities(args.getString(0), args.getString(1)); return new XExtensionResult(status, numbers); } else if (action.equals(COMMAND_GETALLMESSAGES)) { JSONArray messages = getAllMessages(args.getString(0), args.getString(1)); return new XExtensionResult(status, messages); } else if (action.equals(COMMAND_GETMESSAGE)) { JSONObject message = getMessage(args.getString(0), args.getString(1), args.getInt(2)); return new XExtensionResult(status, message); } else if (action.equals(COMMAND_FINDMESSAGES)) { JSONArray messages = findMessages(args.getJSONObject(0), args.getString(1), args.getInt(2), args.getInt(3)); return new XExtensionResult(status, messages); } return new XExtensionResult(status, result); } catch (IllegalArgumentException e) { return new XExtensionResult(XExtensionResult.Status.ERROR); } catch (Exception e) { return new XExtensionResult(XExtensionResult.Status.ERROR); } } @Override public void destroy() { if (null != mSendSMSBroadcastReceiver) { getContext().unregisterReceiver(mSendSMSBroadcastReceiver); mSendSMSBroadcastReceiver = null; } if (null != mMsgReceiveBroadcaseReveiver) { getContext().unregisterReceiver(mMsgReceiveBroadcaseReveiver); mMsgReceiveBroadcaseReveiver = null; } } /** * ???? */ private int getRecordCount(Uri queryUri, String selection, String[] selectionArgs) throws InvalidParameterException { ContentResolver resolver = getContext().getContentResolver(); Cursor cursor = resolver.query(queryUri, new String[] { BaseColumns._ID }, selection, selectionArgs, null); if (null == cursor) { throw new InvalidParameterException(); } final int count = cursor.getCount(); cursor.close(); return count; } /** * ??? * @param messageType ?MMS,SMS,Email * @param folderType * @return ?? */ private int getQuantities(String messageType, String folderType) { //TODO:???Email? if (null == folderType) {// folderTypenull? folderType = FOLDERTYPE_DRAFT; } folderType = folderType.toLowerCase(); Uri uri = Uri.withAppendedPath(mSMSContentUri, folderType); //TODO:?SIM?? final int count = getRecordCount(uri, null, null); return count; } /** * ??? * @param webContext app?app??????UI? * @param messageType ?MMS,SMS,Email * @param addr ? * @param body ? * @param subject ? * @return ? */ private XExtensionResult sendMessage(XIWebContext webContext, String messageType, String addr, String body, String subject) throws IllegalArgumentException { // send SMS if (messageType.equals(MESSAGE_TYPE_SMS)) { return sendSMS(webContext, addr, body); } // send MMS else if (messageType.equals(MESSAGE_TYPE_MMS)) { // TODO:send MMS return new XExtensionResult(XExtensionResult.Status.OK, ""); } // send e-mail else if (messageType.equals(MESSAGE_TYPE_EMAIL)) { return sendEmail(addr, body, subject); } else { throw new IllegalArgumentException("message type illegal"); } } /** * ?? * @param app app?app??????UI? * @param addr ? * @param body ? * @return ? */ private XExtensionResult sendSMS(XIWebContext webContext, String addr, String body) { String regularExpression = "[+*#\\d]+"; if (!addr.matches(regularExpression)) { throw new IllegalArgumentException("address must be digit,*,# or +"); } IntentFilter smsSendIntentFilter = new IntentFilter(SMS_SENT); genSendSMSBroadreceiver(); // ?? getContext().registerReceiver(mSendSMSBroadcastReceiver, smsSendIntentFilter); SmsManager manager = SmsManager.getDefault(); ArrayList<String> textList = manager.divideMessage(body); ArrayList<PendingIntent> smsSendPendingIntentList = genSMSPendingIntentList(textList); manager.sendMultipartTextMessage(addr, null, textList, smsSendPendingIntentList, null); XExtensionResult er = new XExtensionResult(Status.NO_RESULT); er.setKeepCallback(true); return er; } /** * ??Email * @param addr ? * @param body ? * @param subject ? * @return ? */ private XExtensionResult sendEmail(String addr, String body, String subject) { String aEmailList[] = { addr }; Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND); emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, aEmailList); emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, subject); emailIntent.setType("text/plain"); emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, body); getContext().startActivity(emailIntent); return new XExtensionResult(XExtensionResult.Status.OK, ""); } /** * ?? * */ private void genSendSMSBroadreceiver() { if (null == mSendSMSBroadcastReceiver) { mSendSMSBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context arg0, Intent arg1) { // ? SMS_RESULT_STATUS status = SMS_RESULT_STATUS.NO_STATUS; switch (getResultCode()) { case Activity.RESULT_OK:// ??? status = SMS_RESULT_STATUS.SEND_SUCCESS; break; case SmsManager.RESULT_ERROR_GENERIC_FAILURE:// status = SMS_RESULT_STATUS.ERROR_GENERIC_FAILURE; break; case SmsManager.RESULT_ERROR_NO_SERVICE:// ? status = SMS_RESULT_STATUS.ERROR_NO_SERVICE; break; case SmsManager.RESULT_ERROR_NULL_PDU:// PDU?? status = SMS_RESULT_STATUS.ERROR_NULL_PDU; break; case SmsManager.RESULT_ERROR_RADIO_OFF:// status = SMS_RESULT_STATUS.ERROR_RADIO_OFF; break; } resolveSMSSendResult(status); } }; } } /** * PendingIntent * * @param textList * * @return ??pendingIntent * */ private ArrayList<PendingIntent> genSMSPendingIntentList(ArrayList<String> textList) { Intent smsSendIntent = new Intent(SMS_SENT); int count = (null == textList) ? 0 : textList.size(); ArrayList<PendingIntent> smsSendPendingIntentList = new ArrayList<PendingIntent>(count); Iterator<String> itor = textList.iterator(); Context ctx = getContext(); while (itor.hasNext()) { smsSendPendingIntentList.add(PendingIntent.getBroadcast(ctx, 0, smsSendIntent, 0)); itor.next(); } return smsSendPendingIntentList; } /** * ??? * * @param status * ??? * */ private void resolveSMSSendResult(SMS_RESULT_STATUS status) { XExtensionResult er = null; Status extensionStatus = Status.OK; if (status != SMS_RESULT_STATUS.SEND_SUCCESS) { extensionStatus = Status.ERROR; } er = new XExtensionResult(extensionStatus, status.ordinal()); er.setKeepCallback(false); mCallbackCtx.sendExtensionResult(er); } /** * ?? * @param messageType ?MMS,SMS,Email * @param folderType * @param index ? * @return ? */ private JSONObject getMessage(String messageType, String folderType, int index) throws JSONException { //TODO:???Email? if (null == folderType) {// folderTypenull? folderType = FOLDERTYPE_DRAFT; } JSONObject message = new JSONObject(); try { // ??? String[] projection = new String[] { "_id", "subject", "address", "body", "date", "read" }; folderType = folderType.toLowerCase(); Uri uri = Uri.withAppendedPath(mSMSContentUri, folderType); ContentResolver resolver = getContext().getContentResolver(); Cursor cursor = resolver.query(uri, projection, null, null, "date desc"); if (null == cursor) { return message; } // ?? if (!cursor.moveToPosition(index)) { cursor.close(); return message; } //TODO:?SIM?? message = getMessageFromCursor(cursor); cursor.close(); } catch (SQLiteException ex) { ex.printStackTrace(); } return message; } /** * ?? * @param messageType ?MMS,SMS,Email * @param folderType * @return ? */ private JSONArray getAllMessages(String messageType, String folderType) throws JSONException { //TODO:???Email? if (null == folderType) {// folderTypenull? folderType = FOLDERTYPE_DRAFT; } JSONArray messages = new JSONArray(); try { // ??? String[] projection = new String[] { "_id", "subject", "address", "body", "date", "read" }; folderType = folderType.toLowerCase(); Uri uri = Uri.withAppendedPath(mSMSContentUri, folderType); ContentResolver resolver = getContext().getContentResolver(); Cursor cursor = resolver.query(uri, projection, null, null, "date desc"); if (null == cursor) { return messages; } if (!cursor.moveToFirst()) { cursor.close(); return messages; } do { //TODO:?SIM?? JSONObject message = getMessageFromCursor(cursor); messages.put(message); } while (cursor.moveToNext()); cursor.close(); } catch (SQLiteException ex) { ex.printStackTrace(); } return messages; } /** * ? * @param comparisonMsg ?? * @param folderType * @param startIndex * @param endIndex ? * @return ? */ private JSONArray findMessages(JSONObject comparisonMsg, String folderType, int startIndex, int endIndex) throws JSONException { // TODO:???Email? if (null == folderType) {// folderTypenull? folderType = FOLDERTYPE_DRAFT; } ArrayList<String> projections = new ArrayList<String>(); projections.add("_id"); projections.add("subject"); projections.add("address"); projections.add("body"); ArrayList<String> projectionsValue = new ArrayList<String>(); projectionsValue.add(comparisonMsg.optString("messageId")); projectionsValue.add(comparisonMsg.optString("subject")); projectionsValue.add(comparisonMsg.optString("destinationAddresses")); projectionsValue.add(comparisonMsg.optString("body")); StringBuilder selection = XUtils.constructSelectionStatement(projections, projectionsValue); int isRead = comparisonMsg.getInt("isRead"); if (-1 != isRead) { if (null == selection) { selection = new StringBuilder(); } else { selection.append(" AND "); } selection.append("read"); selection.append("="); selection.append(isRead); } String selectionStr = null; if (null != selection) { selectionStr = selection.toString(); } folderType = folderType.toLowerCase(); Uri findUri = Uri.withAppendedPath(mSMSContentUri, folderType); JSONArray messages = new JSONArray(); try { ContentResolver resolver = getContext().getContentResolver(); Cursor cursor = resolver.query(findUri, null, selectionStr, null, null); if (null == cursor) { return messages; } int count = endIndex - startIndex + 1; if (cursor.moveToPosition(startIndex)) { do { JSONObject message = getMessageFromCursor(cursor); messages.put(message); count--; } while (cursor.moveToNext() && count > 0); } cursor.close(); } catch (SQLiteException ex) { ex.printStackTrace(); } return messages; } /** * ?message? */ private JSONObject getMessageFromCursor(Cursor cursor) throws JSONException { //?? String msgId = cursor.getString(cursor.getColumnIndex("_id")); String subject = cursor.getString(cursor.getColumnIndex("subject")); String smsBody = cursor.getString(cursor.getColumnIndex("body")); long date = cursor.getLong(cursor.getColumnIndex("date")); boolean isRead = cursor.getInt(cursor.getColumnIndex("read")) == 0 ? false : true; String destAddress = cursor.getString(cursor.getColumnIndex("address")); JSONObject message = new JSONObject(); message.put("messageId", msgId); message.put("subject", subject); message.put("body", smsBody); message.put("destinationAddresses", destAddress); message.put("messageType", MESSAGE_TYPE_SMS); message.put("date", date); message.put("isRead", isRead); return message; } }