/* * Copyright (C) 2010 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.googlecode.android_scripting.facade; import java.util.ArrayList; import java.util.List; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import android.app.Service; import android.content.ContentResolver; import android.content.ContentUris; import android.content.ContentValues; import android.database.Cursor; import android.net.Uri; import android.telephony.gsm.SmsManager; import com.googlecode.android_scripting.Log; import com.googlecode.android_scripting.jsonrpc.RpcReceiver; import com.googlecode.android_scripting.rpc.Rpc; import com.googlecode.android_scripting.rpc.RpcDefault; import com.googlecode.android_scripting.rpc.RpcOptional; import com.googlecode.android_scripting.rpc.RpcParameter; /** * Provides access to SMS related functionality. * * @author MeanEYE.rcf (meaneye.rcf@gmail.com) */ @SuppressWarnings("deprecation") public class SmsFacade extends RpcReceiver { private final Service mService; private final ContentResolver mContentResolver; private final SmsManager mSms; public SmsFacade(FacadeManager manager) { super(manager); mService = manager.getService(); mContentResolver = mService.getContentResolver(); mSms = SmsManager.getDefault(); } String buildSelectionClause(boolean unreadOnly) { if (unreadOnly) { return "read = 0"; } return ""; } private Uri buildFolderUri(String folder) { Uri.Builder builder = Uri.parse("content://sms").buildUpon(); builder.appendPath(folder); Uri uri = builder.build(); Log.v("Built SMS URI: " + uri); return uri; } private Uri buildMessageUri(Integer id) { Uri.Builder builder = Uri.parse("content://sms").buildUpon(); ContentUris.appendId(builder, id); Uri uri = builder.build(); return uri; } @Rpc(description = "Sends an SMS.") public void smsSend( @RpcParameter(name = "destinationAddress", description = "typically a phone number") String destinationAddress, @RpcParameter(name = "text") String text) { mSms.sendTextMessage(destinationAddress, null, text, null, null); } @Rpc(description = "Returns the number of messages.") public Integer smsGetMessageCount( @RpcParameter(name = "unreadOnly") Boolean unreadOnly, @RpcParameter(name = "folder") @RpcDefault("inbox") String folder) { Uri uri = buildFolderUri(folder); Integer result = 0; String selection = buildSelectionClause(unreadOnly); Cursor cursor = mContentResolver .query(uri, null, selection, null, null); if (cursor != null) { result = cursor.getCount(); cursor.close(); } else { result = 0; } return result; } @Rpc(description = "Returns a List of all message IDs.") public List<Integer> smsGetMessageIds( @RpcParameter(name = "unreadOnly") Boolean unreadOnly, @RpcParameter(name = "folder") @RpcDefault("inbox") String folder) { Uri uri = buildFolderUri(folder); List<Integer> result = new ArrayList<Integer>(); String selection = buildSelectionClause(unreadOnly); String[] columns = { "_id" }; Cursor cursor = mContentResolver.query(uri, columns, selection, null, null); while (cursor != null && cursor.moveToNext()) { result.add(cursor.getInt(0)); } cursor.close(); return result; } @Rpc(description = "Returns a List of all messages.", returns = "a List of messages as Maps") public List<JSONObject> smsGetMessages( @RpcParameter(name = "unreadOnly") Boolean unreadOnly, @RpcParameter(name = "folder") @RpcDefault("inbox") String folder, @RpcParameter(name = "attributes") @RpcOptional JSONArray attributes) throws JSONException { List<JSONObject> result = new ArrayList<JSONObject>(); Uri uri = buildFolderUri(folder); String selection = buildSelectionClause(unreadOnly); String[] columns; if (attributes == null || attributes.length() == 0) { // In case no attributes are specified we set the default ones. columns = new String[] { "_id", "address", "date", "body", "read" }; } else { // Convert selected attributes list into usable string list. columns = new String[attributes.length()]; for (int i = 0; i < attributes.length(); i++) { columns[i] = attributes.getString(i); } } Cursor cursor = mContentResolver.query(uri, columns, selection, null, null); while (cursor != null && cursor.moveToNext()) { JSONObject message = new JSONObject(); for (int i = 0; i < columns.length; i++) { message.put(columns[i], cursor.getString(i)); } result.add(message); } cursor.close(); return result; } @Rpc(description = "Returns message attributes.") public JSONObject smsGetMessageById( @RpcParameter(name = "id", description = "message ID") Integer id, @RpcParameter(name = "attributes") @RpcOptional JSONArray attributes) throws JSONException { JSONObject result = new JSONObject(); Uri uri = buildMessageUri(id); String[] columns; if (attributes == null || attributes.length() == 0) { // In case no attributes are specified we set the default ones. columns = new String[] { "_id", "address", "date", "body", "read" }; } else { // Convert selected attributes list into usable string list. columns = new String[attributes.length()]; for (int i = 0; i < attributes.length(); i++) { columns[i] = attributes.getString(i); } } Cursor cursor = mContentResolver.query(uri, columns, null, null, null); if (cursor != null) { cursor.moveToFirst(); for (int i = 0; i < columns.length; i++) { result.put(columns[i], cursor.getString(i)); } cursor.close(); } else { result = null; } return result; } @Rpc(description = "Returns a List of all possible message attributes.") public List<String> smsGetAttributes() { List<String> result = new ArrayList<String>(); Cursor cursor = mContentResolver.query(Uri.parse("content://sms"), null, null, null, null); if (cursor != null) { String[] columns = cursor.getColumnNames(); for (int i = 0; i < columns.length; i++) { result.add(columns[i]); } cursor.close(); } else { result = null; } return result; } @Rpc(description = "Deletes a message.", returns = "True if the message was deleted") public Boolean smsDeleteMessage(@RpcParameter(name = "id") Integer id) { Uri uri = buildMessageUri(id); Boolean result = false; result = mContentResolver.delete(uri, null, null) > 0; return result; } @Rpc(description = "Marks messages as read.", returns = "number of messages marked read") public Integer smsMarkMessageRead( @RpcParameter(name = "ids", description = "List of message IDs to mark as read.") JSONArray ids, @RpcParameter(name = "read") Boolean read) throws JSONException { Integer result = 0; ContentValues values = new ContentValues(); values.put("read", read); for (int i = 0; i < ids.length(); i++) { Uri uri = buildMessageUri(ids.getInt(i)); result += mContentResolver.update(uri, values, null, null); } return result; } @Override public void shutdown() { } }