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.messaging; import java.security.InvalidParameterException; import java.util.ArrayList; import java.util.Iterator; import org.apache.cordova.CallbackContext; import org.apache.cordova.CordovaInterface; import org.apache.cordova.CordovaPlugin; import org.apache.cordova.CordovaWebView; import org.apache.cordova.PluginResult; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import android.annotation.SuppressLint; 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.XFaceMainActivity; import com.polyvi.xface.event.XEvent; import com.polyvi.xface.event.XEventType; import com.polyvi.xface.event.XSystemEventCenter; import com.polyvi.xface.util.XUtils; public class XMessagingExt extends CordovaPlugin { 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 Context mContext; private CallbackContext mCallbackContext; /** < Intentaction??action */ private static final String INTENT_ACTION = "android.provider.Telephony.SMS_RECEIVED"; private BroadcastReceiver mSendSMSBroadcastReceiver = null; private BroadcastReceiver mMsgReceiveBroadcaseReceiver = null; 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 initialize(CordovaInterface cordova, CordovaWebView webView) { super.initialize(cordova, webView); mContext = cordova.getActivity(); genMsgReceiveBroadcastReceiver(); regMsgReceiver(); } private void genMsgReceiveBroadcastReceiver() { if (null == mMsgReceiveBroadcaseReceiver) { mMsgReceiveBroadcaseReceiver = 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()); ((XFaceMainActivity) mContext).getEventCenter().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() { mContext.registerReceiver(mMsgReceiveBroadcaseReceiver, new IntentFilter(INTENT_ACTION)); } @Override public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { mCallbackContext = callbackContext; try { if (action.equals(COMMAND_SENDMESSAGE)) { sendMessage(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)); callbackContext.success(numbers); } else if (action.equals(COMMAND_GETALLMESSAGES)) { JSONArray messages = getAllMessages(args.getString(0), args.getString(1)); callbackContext.success(messages); } else if (action.equals(COMMAND_GETMESSAGE)) { JSONObject message = getMessage(args.getString(0), args.getString(1), args.getInt(2)); callbackContext.success(message); } else if (action.equals(COMMAND_FINDMESSAGES)) { JSONArray messages = findMessages(args.getJSONObject(0), args.getString(1), args.getInt(2), args.getInt(3)); callbackContext.success(messages); } return true; } catch (IllegalArgumentException e) { } catch (Exception e) { } return false; } @Override public void onDestroy() { if (null != mSendSMSBroadcastReceiver) { mContext.unregisterReceiver(mSendSMSBroadcastReceiver); mSendSMSBroadcastReceiver = null; } if (null != mMsgReceiveBroadcaseReceiver) { mContext.unregisterReceiver(mMsgReceiveBroadcaseReceiver); mMsgReceiveBroadcaseReceiver = null; } } /** * ???? */ private int getRecordCount(Uri queryUri, String selection, String[] selectionArgs) throws InvalidParameterException { ContentResolver resolver = mContext.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 ?? */ @SuppressLint("DefaultLocale") 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 void sendMessage(String messageType, String addr, String body, String subject) throws IllegalArgumentException { // send SMS if (messageType.equals(MESSAGE_TYPE_SMS)) { sendSMS(addr, body); } // send MMS else if (messageType.equals(MESSAGE_TYPE_MMS)) { mCallbackContext.success(); } // send e-mail else if (messageType.equals(MESSAGE_TYPE_EMAIL)) { sendEmail(addr, body, subject); } else { throw new IllegalArgumentException("message type illegal"); } } /** * ?? * * @param app * app?app??????UI? * @param addr * ? * @param body * ? * @return ? */ private void sendSMS(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(); // ?? mContext.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); PluginResult result = new PluginResult(PluginResult.Status.NO_RESULT); result.setKeepCallback(true); mCallbackContext.sendPluginResult(result); } /** * ??Email * * @param addr * ? * @param body * ? * @param subject * ? * @return ? */ private void 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); mContext.startActivity(emailIntent); mCallbackContext.success(); } /** * ?? * */ 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(); while (itor.hasNext()) { smsSendPendingIntentList.add(PendingIntent.getBroadcast(mContext, 0, smsSendIntent, 0)); itor.next(); } return smsSendPendingIntentList; } /** * ??? * * @param status * ??? * */ private void resolveSMSSendResult(SMS_RESULT_STATUS status) { PluginResult.Status callbackStatus = PluginResult.Status.OK; if (status != SMS_RESULT_STATUS.SEND_SUCCESS) { callbackStatus = PluginResult.Status.ERROR; } PluginResult result = new PluginResult(callbackStatus, status.ordinal()); result.setKeepCallback(false); mCallbackContext.sendPluginResult(result); } /** * ?? * * @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 = mContext.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 = mContext.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 = mContext.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; } }