KitKat SMS APIs DevByte Sample Code

Change-Id: I9f0a414e73b37183f4939b95c21c4ce1d5dc52f0
This commit is contained in:
Adam Koch
2013-10-30 15:56:59 -04:00
parent 1c254de3dd
commit e77abcd465
28 changed files with 1019 additions and 0 deletions

View File

@@ -0,0 +1,7 @@
This is an Android Studio project:
http://developer.android.com/sdk/installing/studio.html
To build you should first copy local.properties.sample to
local.properties and set your SDK path.
Then use Android Studio to import the project.

View File

@@ -0,0 +1,43 @@
/*
* Copyright (C) 2013 The Android Open Source Project
*
* 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.
*/
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.6.+'
}
}
apply plugin: 'android'
repositories {
mavenCentral()
}
android {
compileSdkVersion 19
buildToolsVersion "18.1.1"
defaultConfig {
minSdkVersion 10
targetSdkVersion 19
}
}
dependencies {
compile 'com.android.support:support-v4:18.0.0'
}

View File

@@ -0,0 +1,138 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2013 The Android Open Source Project
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.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.smssample"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="10"
android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.WRITE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.RECEIVE_MMS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:windowSoftInputMode="stateHidden">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<action android:name="android.intent.action.SENDTO" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="sms" />
<data android:scheme="smsto" />
<data android:scheme="mms" />
<data android:scheme="mmsto" />
</intent-filter>
</activity>
<!-- BroadcastReceiver that listens for incoming SMS messages -->
<!-- Note the use of android:enabled that is linked to a bool. This will mean this receiver
is enabled on KitKat devices and above -->
<receiver android:name=".receiver.SmsReceiver"
android:enabled="@bool/hasKitKat"
android:permission="android.permission.BROADCAST_SMS">
<!-- KitKat+ SMS received action -->
<intent-filter>
<action android:name="android.provider.Telephony.SMS_DELIVER" />
</intent-filter>
</receiver>
<!-- BroadcastReceiver that listens for incoming SMS messages -->
<!-- Note the use of android:enabled that is linked to a bool. This will mean this receiver
is enabled on preKitKat devices -->
<receiver android:name=".receiver.SmsReceiverLegacy"
android:enabled="@bool/preKitKat">
<!-- Pre-KitKat SMS received action -->
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
<!-- BroadcastReceiver that listens for incoming MMS messages -->
<!-- Note the use of android:enabled that is linked to a bool. This will mean this receiver
is enabled on KitKat devices and above -->
<receiver android:name=".receiver.MmsReceiver"
android:enabled="@bool/hasKitKat"
android:permission="android.permission.BROADCAST_WAP_PUSH">
<!-- KitKat+ MMS received action -->
<intent-filter>
<action android:name="android.provider.Telephony.WAP_PUSH_DELIVER" />
<data android:mimeType="application/vnd.wap.mms-message" />
</intent-filter>
</receiver>
<!-- BroadcastReceiver that listens for incoming MMS messages -->
<!-- Note the use of android:enabled that is linked to a bool. This will mean this receiver
is enabled on preKitKat devices -->
<receiver android:name=".receiver.MmsReceiverLegacy"
android:enabled="@bool/preKitKat">
<!-- Pre-KitKat MMS received action -->
<intent-filter>
<action android:name="android.provider.Telephony.WAP_PUSH_RECEIVED" />
<data android:mimeType="application/vnd.wap.mms-message" />
</intent-filter>
</receiver>
<!-- Service that delivers SMS messages received from the phone "quick response" -->
<service android:name=".service.RespondService"
android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.RESPOND_VIA_MESSAGE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="sms" />
<data android:scheme="smsto" />
<data android:scheme="mms" />
<data android:scheme="mmsto" />
</intent-filter>
</service>
<!-- A service used internally to process incoming SMS/MMS -->
<service android:name=".service.MessagingService"
android:exported="false" />
</application>
</manifest>

View File

@@ -0,0 +1,203 @@
/*
* Copyright (C) 2013 The Android Open Source Project
*
* 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.example.android.smssample;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Telephony.Sms.Inbox;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.widget.SimpleCursorAdapter;
import android.text.TextUtils;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.Toast;
/**
* The main Activity that provides a sample of a few things:
* -detecting if this app is the default SMS app and then showing/hiding UI and enabling/disabling
* functionality. the UI that is shown has a button to prompt the user to set this app as the
* default.
* -a simple query to the SMS content provider to show a list of SMS messages in the inbox. even
* though the query uses KitKat APIs this query should still work on earlier versions of Android
* as the contract class and ContentProvider were still around (with essentially the same
* structure) but were private.
* -being triggered from another application when creating a new SMS. a good example is creating
* a new SMS from the system People application. although nothing is done with the incoming
* Intent in this case (just a Toast is displayed)
*
* Obviously this is far from a full implementation and should just be used as a sample of how
* an app could be set up to correctly integrate with the new Android 4.4 KitKat APIs while
* running normally on earlier Android versions.
*/
public class MainActivity extends FragmentActivity implements LoaderCallbacks<Cursor> {
private RelativeLayout mSetDefaultSmsLayout;
private Button mSendSmsButton;
private EditText mSendSmsEditText;
private SimpleCursorAdapter mAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Find some views
mSetDefaultSmsLayout = (RelativeLayout) findViewById(R.id.set_default_sms_layout);
mSendSmsEditText = (EditText) findViewById(R.id.send_sms_edittext);
ListView listView = (ListView) findViewById(android.R.id.list);
listView.setEmptyView(findViewById(android.R.id.empty));
mSendSmsButton = (Button) findViewById(R.id.send_sms_button);
mSendSmsButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
sendSms(mSendSmsEditText.getText().toString());
}
});
// Create adapter and set it to our ListView
final String[] fromFields = new String[] {
SmsQuery.PROJECTION[SmsQuery.ADDRESS], SmsQuery.PROJECTION[SmsQuery.BODY] };
final int[] toViews = new int[] { android.R.id.text1, android.R.id.text2 };
mAdapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_2, null,
fromFields, toViews, 0);
listView.setAdapter(mAdapter);
// Placeholder to process incoming SEND/SENDTO intents
String intentAction = getIntent() == null ? null : getIntent().getAction();
if (!TextUtils.isEmpty(intentAction) && (Intent.ACTION_SENDTO.equals(intentAction)
|| Intent.ACTION_SEND.equals(intentAction))) {
// TODO: Handle incoming SEND and SENDTO intents by pre-populating UI components
Toast.makeText(this, "Handle SEND and SENDTO intents: " + getIntent().getDataString(),
Toast.LENGTH_SHORT).show();
}
// Simple query to show the most recent SMS messages in the inbox
getSupportLoaderManager().initLoader(SmsQuery.TOKEN, null, this);
}
/**
* Dummy sendSms method, would need the "to" address to actually send a message :)
*/
private void sendSms(String smsText) {
if (!TextUtils.isEmpty(smsText)) {
if (Utils.isDefaultSmsApp(this)) {
// TODO: Use SmsManager to send SMS and then record the message in the system SMS
// ContentProvider
Toast.makeText(this, "Sending text message: " + smsText, Toast.LENGTH_SHORT).show();
} else {
// TODO: Notify the user the app is not default and provide a way to trigger
// Utils.setDefaultSmsApp() so they can set it.
Toast.makeText(this, "Not default", Toast.LENGTH_SHORT).show();
}
}
}
@Override
protected void onResume() {
super.onResume();
// Only do these checks/changes on KitKat+, the "mSetDefaultSmsLayout" has its visibility
// set to "gone" in the xml layout so it won't show at all on earlier Android versions.
if (Utils.hasKitKat()) {
if (Utils.isDefaultSmsApp(this)) {
// This app is the default, remove the "make this app the default" layout and
// enable message sending components.
mSetDefaultSmsLayout.setVisibility(View.GONE);
mSendSmsEditText.setHint(R.string.sms_send_new_hint);
mSendSmsEditText.setEnabled(true);
mSendSmsButton.setEnabled(true);
} else {
// Not the default, show the "make this app the default" layout and disable
// message sending components.
mSetDefaultSmsLayout.setVisibility(View.VISIBLE);
mSendSmsEditText.setText("");
mSendSmsEditText.setHint(R.string.sms_send_disabled);
mSendSmsEditText.setEnabled(false);
mSendSmsButton.setEnabled(false);
Button button = (Button) findViewById(R.id.set_default_sms_button);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
Utils.setDefaultSmsApp(MainActivity.this);
}
});
}
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
if (i == SmsQuery.TOKEN) {
// This will fetch all SMS messages in the inbox, ordered by date desc
return new CursorLoader(this, SmsQuery.CONTENT_URI, SmsQuery.PROJECTION, null, null,
SmsQuery.SORT_ORDER);
}
return null;
}
@Override
public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) {
if (cursorLoader.getId() == SmsQuery.TOKEN && cursor != null) {
// Standard swap cursor in when load is done
mAdapter.swapCursor(cursor);
}
}
@Override
public void onLoaderReset(Loader<Cursor> cursorLoader) {
// Standard swap cursor to null when loader is reset
mAdapter.swapCursor(null);
}
/**
* A basic SmsQuery on android.provider.Telephony.Sms.Inbox
*/
private interface SmsQuery {
int TOKEN = 1;
static final Uri CONTENT_URI = Inbox.CONTENT_URI;
static final String[] PROJECTION = {
Inbox._ID,
Inbox.ADDRESS,
Inbox.BODY,
};
static final String SORT_ORDER = Inbox.DEFAULT_SORT_ORDER;
int ID = 0;
int ADDRESS = 1;
int BODY = 2;
}
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright (C) 2013 The Android Open Source Project
*
* 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.example.android.smssample;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Build.VERSION_CODES;
import android.provider.Telephony;
import android.provider.Telephony.Sms.Intents;
public class Utils {
/**
* Check if the device runs Android 4.3 (JB MR2) or higher.
*/
public static boolean hasJellyBeanMR2() {
return Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR2;
}
/**
* Check if the device runs Android 4.4 (KitKat) or higher.
*/
public static boolean hasKitKat() {
return Build.VERSION.SDK_INT >= VERSION_CODES.KITKAT;
}
/**
* Check if your app is the default system SMS app.
* @param context The Context
* @return True if it is default, False otherwise. Pre-KitKat will always return True.
*/
public static boolean isDefaultSmsApp(Context context) {
if (hasKitKat()) {
return context.getPackageName().equals(Telephony.Sms.getDefaultSmsPackage(context));
}
return true;
}
/**
* Trigger the intent to open the system dialog that asks the user to change the default
* SMS app.
* @param context The Context
*/
public static void setDefaultSmsApp(Context context) {
// This is a new intent which only exists on KitKat
if (hasKitKat()) {
Intent intent = new Intent(Intents.ACTION_CHANGE_DEFAULT);
intent.putExtra(Intents.EXTRA_PACKAGE_NAME, context.getPackageName());
context.startActivity(intent);
}
}
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright (C) 2013 The Android Open Source Project
*
* 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.example.android.smssample.receiver;
import android.content.Context;
import android.content.Intent;
import android.provider.Telephony.Sms.Intents;
import android.support.v4.content.WakefulBroadcastReceiver;
import com.example.android.smssample.service.MessagingService;
import com.example.android.smssample.Utils;
/**
* The main messaging receiver class. Note that this is not directly included in
* AndroidManifest.xml, instead, subclassed versions of this are included which allows
* them to be enabled/disabled independently as they will have a unique component name.
*/
public class MessagingReceiver extends WakefulBroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent == null ? null : intent.getAction();
// If on KitKat+ and default messaging app then look for new deliver actions actions.
if (Utils.hasKitKat() && Utils.isDefaultSmsApp(context)) {
if (Intents.SMS_DELIVER_ACTION.equals(action)) {
handleIncomingSms(context, intent);
} else if (Intents.WAP_PUSH_DELIVER_ACTION.equals(action)) {
handleIncomingMms(context, intent);
}
} else { // Otherwise look for old pre-KitKat actions
if (Intents.SMS_RECEIVED_ACTION.equals(action)) {
handleIncomingSms(context, intent);
} else if (Intents.WAP_PUSH_RECEIVED_ACTION.equals(action)) {
handleIncomingMms(context, intent);
}
}
}
private void handleIncomingSms(Context context, Intent intent) {
// TODO: Handle SMS here
// As an example, we'll start a wakeful service to handle the SMS
intent.setAction(MessagingService.ACTION_MY_RECEIVE_SMS);
intent.setClass(context, MessagingService.class);
startWakefulService(context, intent);
}
private void handleIncomingMms(Context context, Intent intent) {
// TODO: Handle MMS here
// As an example, we'll start a wakeful service to handle the MMS
intent.setAction(MessagingService.ACTION_MY_RECEIVE_MMS);
intent.setClass(context, MessagingService.class);
startWakefulService(context, intent);
}
}

View File

@@ -0,0 +1,24 @@
/*
* Copyright (C) 2013 The Android Open Source Project
*
* 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.example.android.smssample.receiver;
/**
* Stub subclass to allow individual receiver components in AndroidManifest to be enabled/disabled.
*/
public class MmsReceiver extends MessagingReceiver {
}

View File

@@ -0,0 +1,24 @@
/*
* Copyright (C) 2013 The Android Open Source Project
*
* 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.example.android.smssample.receiver;
/**
* Stub subclass to allow individual receiver components in AndroidManifest to be enabled/disabled.
*/
public class MmsReceiverLegacy extends MessagingReceiver {
}

View File

@@ -0,0 +1,24 @@
/*
* Copyright (C) 2013 The Android Open Source Project
*
* 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.example.android.smssample.receiver;
/**
* Stub subclass to allow individual receiver components in AndroidManifest to be enabled/disabled.
*/
public class SmsReceiver extends MessagingReceiver {
}

View File

@@ -0,0 +1,24 @@
/*
* Copyright (C) 2013 The Android Open Source Project
*
* 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.example.android.smssample.receiver;
/**
* Stub subclass to allow individual receiver components in AndroidManifest to be enabled/disabled.
*/
public class SmsReceiverLegacy extends MessagingReceiver {
}

View File

@@ -0,0 +1,58 @@
/*
* Copyright (C) 2013 The Android Open Source Project
*
* 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.example.android.smssample.service;
import android.app.IntentService;
import android.content.Intent;
import com.example.android.smssample.receiver.MessagingReceiver;
/**
* This service is triggered internally only and is used to process incoming SMS and MMS messages
* that the {@link com.example.android.smssample.receiver.MessagingReceiver} passes over. It's
* preferable to handle these in a service in case there is significant work to do which may exceed
* the time allowed in a receiver.
*/
public class MessagingService extends IntentService {
private static final String TAG = "MessagingService";
// These actions are for this app only and are used by MessagingReceiver to start this service
public static final String ACTION_MY_RECEIVE_SMS = "com.example.android.smssample.RECEIVE_SMS";
public static final String ACTION_MY_RECEIVE_MMS = "com.example.android.smssample.RECEIVE_MMS";
public MessagingService() {
super(TAG);
}
@Override
protected void onHandleIntent(Intent intent) {
if (intent != null) {
String intentAction = intent.getAction();
if (ACTION_MY_RECEIVE_SMS.equals(intentAction)) {
// TODO: Handle incoming SMS
// Ensure wakelock is released that was created by the WakefulBroadcastReceiver
MessagingReceiver.completeWakefulIntent(intent);
} else if (ACTION_MY_RECEIVE_MMS.equals(intentAction)) {
// TODO: Handle incoming MMS
// Ensure wakelock is released that was created by the WakefulBroadcastReceiver
MessagingReceiver.completeWakefulIntent(intent);
}
}
}
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright (C) 2013 The Android Open Source Project
*
* 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.example.android.smssample.service;
import android.app.IntentService;
import android.content.Intent;
import android.telephony.TelephonyManager;
import com.example.android.smssample.Utils;
/**
* This service handles the system intent ACTION_RESPOND_VIA_MESSAGE when we are the default SMS
* app.
*/
public class RespondService extends IntentService {
private static final String TAG = "RespondService";
public RespondService() {
super(TAG);
}
@Override
protected void onHandleIntent(Intent intent) {
if (intent != null) {
if (Utils.hasJellyBeanMR2() && Utils.isDefaultSmsApp(this) &&
// ACTION_RESPOND_VIA_MESSAGE was added in JB MR2
TelephonyManager.ACTION_RESPOND_VIA_MESSAGE.equals(intent.getAction())) {
// TODO: Handle "respond via message" quick reply
}
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

View File

@@ -0,0 +1,93 @@
<!--
Copyright (C) 2013 The Android Open Source Project
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.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<RelativeLayout
android:id="@+id/set_default_sms_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:background="@color/alert_orange">
<Button
android:id="@+id/set_default_sms_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_margin="@dimen/standard_margin"
android:text="@string/choose_sms_app" />
<TextView
android:id="@+id/set_default_sms_textview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toLeftOf="@+id/set_default_sms_button"
android:layout_centerVertical="true"
android:layout_margin="@dimen/standard_margin"
android:text="@string/set_default_sms_text" />
</RelativeLayout>
<ListView
android:id="@android:id/list"
android:layout_height="0dp"
android:layout_width="match_parent"
android:layout_weight="1"
android:fastScrollEnabled="true" />
<TextView
android:id="@android:id/empty"
android:layout_height="0dp"
android:layout_width="match_parent"
android:layout_weight="1"
android:gravity="center"
android:visibility="gone"
android:layout_margin="@dimen/standard_margin"
style="?android:textAppearanceMedium"
android:text="@string/sms_empty" />
<RelativeLayout
android:id="@+id/send_sms_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/standard_margin"
android:background="@color/light_gray">
<Button
android:id="@+id/send_sms_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:text="@string/sms_send" />
<EditText
android:id="@+id/send_sms_edittext"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toLeftOf="@+id/send_sms_button"
android:layout_centerVertical="true"
android:hint="@string/sms_send_new_hint"/>
</RelativeLayout>
</LinearLayout>

View File

@@ -0,0 +1,23 @@
<!--
Copyright (C) 2013 The Android Open Source Project
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.
-->
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/action_default"
android:title="@string/action_settings"
android:orderInCategory="100"
android:showAsAction="never" />
</menu>

View File

@@ -0,0 +1,26 @@
<!--
Copyright (C) 2013 The Android Open Source Project
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.
-->
<resources>
<!--
Base application theme for API 11+. This theme completely replaces
AppBaseTheme from res/values/styles.xml on API 11+ devices.
-->
<style name="AppBaseTheme" parent="android:Theme.Holo.Light">
<!-- API 11 theme customizations can go here. -->
</style>
</resources>

View File

@@ -0,0 +1,19 @@
<!--
Copyright (C) 2013 The Android Open Source Project
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.
-->
<resources>
<bool name="hasKitKat">true</bool>
<bool name="preKitKat">false</bool>
</resources>

View File

@@ -0,0 +1,19 @@
<!--
Copyright (C) 2013 The Android Open Source Project
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.
-->
<resources>
<bool name="hasKitKat">false</bool>
<bool name="preKitKat">true</bool>
</resources>

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2013 The Android Open Source Project
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.
-->
<resources>
<color name="alert_orange">#FFBB33</color>
<color name="light_gray">#F4F4F4</color>
</resources>

View File

@@ -0,0 +1,19 @@
<!--
Copyright (C) 2013 The Android Open Source Project
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.
-->
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="standard_margin">8dp</dimen>
</resources>

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2013 The Android Open Source Project
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.
-->
<resources>
<string name="app_name">SmsDemoApp</string>
<string name="action_settings">Settings</string>
<string name="choose_sms_app">Set as default</string>
<string name="sms_empty">No SMS messages</string>
<string name="set_default_sms_text">This app is not the default SMS app</string>
<string name="sms_send_new_hint">Send new SMS</string>
<string name="sms_send">Send</string>
<string name="sms_send_disabled">SMS Sending Disabled</string>
</resources>

View File

@@ -0,0 +1,35 @@
<!--
Copyright (C) 2013 The Android Open Source Project
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.
-->
<resources>
<!--
Base application theme, dependent on API level. This theme is replaced
by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
-->
<style name="AppBaseTheme" parent="android:Theme.Light">
<!--
Theme customizations available in newer API levels can go in
res/values-vXX/styles.xml, while customizations related to
backward-compatibility can go here.
-->
</style>
<!-- Application theme. -->
<style name="AppTheme" parent="AppBaseTheme">
<!-- All customizations that are NOT specific to a particular API-level can go here. -->
</style>
</resources>

View File

@@ -0,0 +1 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.

View File

@@ -0,0 +1,7 @@
# This file should be copied to local.properties and path set to point
# to your Android SDK.
# Location of the SDK. This is only used by Gradle.
# For customization when using a Version Control System, please read the
# header note.
sdk.dir=/usr/local/lib/android-sdk

View File

@@ -0,0 +1 @@
include ':SmsSample'