Android-->发送短信页面实现(短信发送以及群发和从电话本中选择联系人)-----------》2

时间:2023-03-08 16:19:53
Android-->发送短信页面实现(短信发送以及群发和从电话本中选择联系人)-----------》2

分析下怎么写

首先,我们需要一个输入框,可以手动的输入手机号码,

其次,很少有人愿意手动输入,那么我们需要提供一个按钮来给我们的用户选择自己电话本中的联系人(一次可以选择多个即群发)

然后,我们需要一个短信编辑界面,可以编辑短信

最后两个按钮,一个发送,点击后发送消息,一个取消(取消后存为草稿,目前没有开发)

Android-->发送短信页面实现(短信发送以及群发和从电话本中选择联系人)-----------》2

这个是我的UI,当然很难看,后续会优化

先把布局文件放上来,就不多分析了,布局很简单,里面需要的图片就自己找个地方抠一下了  activity_newmessage.xml

<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@color/title"
android:gravity="center" > <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/newmessage_tools"
android:textColor="#ffffff"
android:textSize="25dp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_weight="1"
android:gravity="center_vertical">
<EditText
android:id="@+id/et_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="@string/phonenumber_body"
android:ems="10"
android:layout_weight="3"
android:inputType="phone" >
<requestFocus />
</EditText> <Button
android:id="@+id/bt_contact"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_weight="1"
android:background="@drawable/add_contact_selector"/>
</LinearLayout>
<EditText
android:id="@+id/et_content"
android:gravity="top"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="8"
android:hint="@string/message_body"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center_vertical"
android:layout_weight="1">
<Button
android:id="@+id/bt_send"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@drawable/button_selector"
android:text="@string/send"/>
<Button
android:id="@+id/bt_cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@drawable/button_selector"
android:text="@string/cancel"/>
</LinearLayout>

再给大家一个按钮  selector吧button_selector

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:drawable="@drawable/sms_add_contact_pressed" /> <!-- pressed -->
<item android:state_focused="true"
android:drawable="@drawable/sms_add_contact_pressed" /> <!-- focused -->
<item android:drawable="@drawable/sms_add_contact_nomal" /> <!-- default -->
</selector>

然后点击那个小人按钮,我们需要载入联系人如下图:

Android-->发送短信页面实现(短信发送以及群发和从电话本中选择联系人)-----------》2

目前写了一个全部联系人,当然支持从手机联系人选择和sim卡选择问题也不大的

Android-->发送短信页面实现(短信发送以及群发和从电话本中选择联系人)-----------》2

模拟器上联系人比较少。

选择联系人以后,点击确认,会自动将联系人填写到发送短信页面的电话号码那个EDITTEXT中

下面再把这个页面的布局放上来,

<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center"
android:background="@color/title">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/title_contact"
android:textColor="#ffffff"
android:textSize="25dp"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center_vertical"
android:layout_weight="1">
<Button
android:id="@+id/bt_selectall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@drawable/button_selector"
android:text="@string/selectall"/>
<Button
android:id="@+id/bt_selectnone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@drawable/button_selector"
android:text="@string/selectnone"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="4"> <ListView
android:id="@+id/lv_contact"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center_vertical"
android:layout_weight="1">
<Button
android:id="@+id/bt_sure"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@drawable/button_selector"
android:text="@string/sure"/>
<Button
android:id="@+id/bt_cl"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@drawable/button_selector"
android:text="@string/cancel"/>
</LinearLayout>

ok,界面的工作到此结束,接下来我们就要开始代码的编写了,新建消息页面

package com.xiaoxu.message;

import java.util.ArrayList;
import java.util.List; import android.app.Activity;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.telephony.SmsManager;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast; import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.xiaoxu.message.bean.ContactInfo;
import com.xiaoxu.message.util.SoundPoolButton; public class NewMessageActivity extends Activity implements OnClickListener {
private SoundPoolButton soundpool;
private EditText numET;
private EditText contentET;
private Button addcontact,send,cancel;
private List<ContactInfo> select; /* 自定义ACTION常数,作为广播的Intent Filter识别常数 */
private static String SMS_SEND_ACTIOIN = "SMS_SEND_ACTIOIN";
private static String SMS_DELIVERED_ACTION = "SMS_DELIVERED_ACTION";
private mServiceReceiver mReceiver01, mReceiver02; protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_newmessage);
soundpool = new SoundPoolButton(this); numET = (EditText) findViewById(R.id.et_number); // 获取2个文本框
contentET = (EditText) findViewById(R.id.et_content); addcontact = (Button) findViewById(R.id.bt_contact);
send = (Button) findViewById(R.id.bt_send);
cancel = (Button) findViewById(R.id.bt_cancel); addcontact.setOnClickListener(this);
send.setOnClickListener(this);
cancel.setOnClickListener(this);
} private void send() {
//获取到了所有联系人
String num = numET.getText().toString().trim(); // 获取电话号码和短信内容
String content = contentET.getText().toString();
String number = "";
// 截取联系人
if(!num.endsWith(";")){
num += ";";
//拿一个号码,发一个号码
number = num.substring(0, num.indexOf(";"));
/* 建立SmsManager对象 */
SmsManager smsManager = SmsManager.getDefault();
/* 建立自定义Action常数的Intent(给PendingIntent参数之用) */
Intent itSend = new Intent(SMS_SEND_ACTIOIN);
Intent itDeliver = new Intent(SMS_DELIVERED_ACTION);
/* sentIntent参数为传送后接受的广播信息PendingIntent */
PendingIntent mSendPI = PendingIntent.getBroadcast(getApplicationContext(), 0, itSend, 0);
/* deliveryIntent参数为送达后接受的广播信息PendingIntent */
PendingIntent mDeliverPI = PendingIntent.getBroadcast(getApplicationContext(), 0, itDeliver, 0);
ArrayList<String> list = smsManager.divideMessage(content); // 使用短信管理器把短信分段
if (list.size() == 0) {
Toast.makeText(getApplicationContext(), R.string.content_empty, Toast.LENGTH_SHORT).show(); // 弹出通知
return;
}
for (String sms : list) { // 逐段发送
smsManager.sendTextMessage(number, null, sms, mSendPI, mDeliverPI); // 使用短信管理器发送指定内容到指定号码上
}
return;
} while(num.length()>0){
//拿一个号码,发一个号码
number = num.substring(0, num.indexOf(";")); /* 建立SmsManager对象 */
SmsManager smsManager = SmsManager.getDefault();
/* 建立自定义Action常数的Intent(给PendingIntent参数之用) */
Intent itSend = new Intent(SMS_SEND_ACTIOIN);
// Intent itDeliver = new Intent(SMS_DELIVERED_ACTION);
/* sentIntent参数为传送后接受的广播信息PendingIntent */
PendingIntent mSendPI = PendingIntent.getBroadcast(getApplicationContext(), 0, itSend, 0); /* deliveryIntent参数为送达后接受的广播信息PendingIntent */
//暂时不使用,为了绕过系统提示发消息
// PendingIntent mDeliverPI = PendingIntent.getBroadcast(getApplicationContext(), 0, itDeliver, 0);
// /* 发送SMS短信,注意倒数的两个PendingIntent参数 */
// smsManager.sendTextMessage(number, null, content, mSendPI, mDeliverPI);
//
ArrayList<String> list = smsManager.divideMessage(content); // 使用短信管理器把短信分段
if (list.size() == 0) {
Toast.makeText(getApplicationContext(), R.string.content_empty, Toast.LENGTH_SHORT).show(); // 弹出通知
return;
}
for (String sms : list) { // 逐段发送
smsManager.sendTextMessage(number, null, sms, mSendPI, null); // 使用短信管理器发送指定内容到指定号码上
} if(num.length()>num.indexOf(";")+1){
num = num.substring(num.indexOf(";")+1);
}else{
break;
}
}
} @Override
public void onClick(View view) {
soundpool.play();
switch(view.getId()){
case R.id.bt_contact:
String[] items={"查看全部","查看SIM卡","查看手机"};
new AlertDialog.Builder(this) //
.setTitle("选择联系人") //
.setCancelable(true) //
.setItems(items, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
switch(which){
case 0:
Intent intent = new Intent(NewMessageActivity.this,ContactActivity.class);
startActivityForResult(intent, 0);
break;
case 1:break;
case 2:break;
}
}
}) // listener 为OnClickListener 监听器对象, 监听列表项被选中
.show();
break;
case R.id.bt_send:
send();
//TODO 跳转到发送消息页面
break;
case R.id.bt_cancel:
finish();
break;
} }
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(data!=null){
Gson gson = new Gson();
// System.out.println(data.getStringExtra("return"));
String str = data.getStringExtra("return");
select = gson.fromJson(str, new TypeToken<ArrayList<ContactInfo>>(){}.getType());
String number = new String();
for(int i= 0;i<select.size();i++){
if(number!=null&&number.length()>1){
number += ";"+select.get(i).getUserNumber();
}else{
number = select.get(i).getUserNumber();
}
}
number+=";";
numET.setText(number);
super.onActivityResult(requestCode, resultCode, data);
}
} /**
*
* 自定义mServiceReceiver重写BroadcastReceiver监听短信状态信息
*
*/
public class mServiceReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
if (intent.getAction().equals(SMS_SEND_ACTIOIN))
{
try
{
switch(getResultCode())
{
case Activity.RESULT_OK:
/* 发送短信成功 */
Toast.makeText(getApplicationContext(), "发送成功", 0).show();
contentET.setText("");
break;
case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
/* 发送短信失败 */
Toast.makeText(getApplicationContext(), "发送失败", 0).show();
break;
case SmsManager.RESULT_ERROR_RADIO_OFF:
break;
case SmsManager.RESULT_ERROR_NULL_PDU:
break;
}
}
catch(Exception e)
{
Toast.makeText(getApplicationContext(), "发送失败", 0).show();
e.getStackTrace();
}
}
//暂时未使用
else if(intent.getAction().equals(SMS_DELIVERED_ACTION))
{
try
{
/* android.content.BroadcastReceiver.getResultCode()方法 */
switch(getResultCode())
{
case Activity.RESULT_OK:
/* 短信 */
Toast.makeText(getApplicationContext(), "发送成功", 0).show();
break;
case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
/* 短信未送达 */
Toast.makeText(getApplicationContext(), "发送失败", 0).show();
break;
case SmsManager.RESULT_ERROR_RADIO_OFF:
break;
case SmsManager.RESULT_ERROR_NULL_PDU:
break;
}
}
catch(Exception e)
{
Toast.makeText(getApplicationContext(), "发送失败", 0).show();
e.getStackTrace();
}
}
}
} //这是重载Activity中的函数
@Override
protected void onResume()
{
/* 自定义IntentFilter为SENT_SMS_ACTIOIN Receiver */
IntentFilter mFilter01;
mFilter01 = new IntentFilter(SMS_SEND_ACTIOIN);
mReceiver01 = new mServiceReceiver();
registerReceiver(mReceiver01, mFilter01); /* 自定义IntentFilter为DELIVERED_SMS_ACTION Receiver */
mFilter01 = new IntentFilter(SMS_DELIVERED_ACTION);
mReceiver02 = new mServiceReceiver();
registerReceiver(mReceiver02, mFilter01); super.onResume();
} @Override
protected void onPause()
{
/* 取消注册自定义Receiver */
unregisterReceiver(mReceiver01);
unregisterReceiver(mReceiver02);
super.onPause();
} }

注意点:

1:跳转到联系人页面的时候,我们使用startactivityforresult,这样我们可以将选择的联系人的信息带过来到这个页面。
2:发送短信

            smsManager.sendTextMessage(number, null, content, mSendPI, null);  

这个方法,第一个参数是电话号码,第二个参数不管,第三个参数是短信内容,第四个参数是发送状态的广播接受者,第四个参数是对方是否接收到的接受者

还要注意 如果我们将第三个和第四个接收者都填写的话,android系统会跳出一个提示框,说应用正在发送短信,这个很不理想,所以我们只填写 mSendPI这个接收者

3:我们的广播接收者在当前页面定义就Ok了,但是在什么时候注册,什么时候取消注册是关键。我们只有当当前页面获取到了焦点之后才需要注册,在失去焦点时取消注册,就OK了

接下来是选择联系人页面代码

package com.xiaoxu.message;
import java.util.ArrayList;
import java.util.List; import android.app.Activity;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.ListView; import com.google.gson.Gson;
import com.xiaoxu.message.adapter.ContactAdapter;
import com.xiaoxu.message.bean.ContactInfo;
import com.xiaoxu.message.util.SoundPoolButton; public class ContactActivity extends Activity implements OnClickListener {
private List<ContactInfo> contactlist;
private ListView listview;
private ContactAdapter adapter;
private Button selectall,selectnone,sure,cancel;
private SoundPoolButton soundpool; /** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_contacts);
init();
} private void init(){
contactlist = new ArrayList<ContactInfo>();
selectall = (Button) findViewById(R.id.bt_selectall);
selectnone = (Button) findViewById(R.id.bt_selectnone);
sure = (Button) findViewById(R.id.bt_sure);
cancel = (Button) findViewById(R.id.bt_cl);
listview = (ListView) findViewById(R.id.lv_contact);
soundpool = new SoundPoolButton(this);
adapter = new ContactAdapter(contactlist,this); // new Thread(){
// public void run() {
getAllContacts();
// };
// }.start(); listview.setAdapter(adapter);
listview.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View view, int position,
long arg3) {
// TODO Auto-generated method stub
}
}); selectall.setOnClickListener(this);
selectnone.setOnClickListener(this);
sure.setOnClickListener(this);
cancel.setOnClickListener(this);
} private void getAllContacts(){
// 获得所有的联系人
Cursor cur = getContentResolver().query(
ContactsContract.Contacts.CONTENT_URI,
null,null,null,
ContactsContract.Contacts.DISPLAY_NAME
+ " COLLATE LOCALIZED ASC");
// 循环遍历
if (cur.moveToFirst()) {
int idColumn = cur.getColumnIndex(ContactsContract.Contacts._ID);
int displayNameColumn = cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
while (cur.moveToNext()){
ContactInfo contact = new ContactInfo();
// 获得联系人的ID号
String contactId = cur.getString(idColumn);
// 获得联系人姓名
String disPlayName = cur.getString(displayNameColumn);
contact.setContactName(disPlayName);
// 查看该联系人有多少个电话号码。如果没有这返回值为0
int phoneCount = cur.getInt(cur.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER));
if (phoneCount > 0) {
// 获得联系人的电话号码
Cursor phones = getContentResolver().query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,ContactsContract.CommonDataKinds.Phone.CONTACT_ID
+ " = " + contactId, null, null);
if (phones.moveToFirst()) {
do {
// 遍历所有的电话号码
String phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
contact.setUserNumber(phoneNumber);
} while (phones.moveToNext());
}
phones.close(); }
contactlist.add(contact);
}
}
cur.close();
} @Override
public void onClick(View v) {
Gson gson = new Gson();
Intent intent = new Intent();
soundpool.play();
switch(v.getId()){
case R.id.bt_selectall:
for(int i=0;i<contactlist.size();i++){
contactlist.get(i).setChecked(true);
}
adapter.notifyDataSetChanged();
break;
case R.id.bt_selectnone:
for(int i=0;i<contactlist.size();i++){
contactlist.get(i).setChecked(false);
}
adapter.notifyDataSetChanged();
break;
case R.id.bt_sure:
ArrayList<ContactInfo> select = new ArrayList<ContactInfo>();
for(int i=0;i<contactlist.size();i++){
if(contactlist.get(i).getChecked()){
select.add(contactlist.get(i));
}
}
String str = gson.toJson(select);
intent.putExtra("return", str);
setResult(RESULT_OK, intent);
finish();
break;
case R.id.bt_cl:
setResult(RESULT_CANCELED, null);
finish();
break;
} }
}

还有里面用到的适配器(因为比较懒,所以这个listview暂时还没有进行优化的,大家莫怪)

package com.xiaoxu.message.adapter;

import java.util.List;

import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.TextView; import com.xiaoxu.message.R;
import com.xiaoxu.message.bean.ContactInfo; public class ContactAdapter extends BaseAdapter{
private List<ContactInfo> contactlist;
private Context context; public ContactAdapter(List<ContactInfo> contactlist,Context context) {
this.contactlist = contactlist;
this.context = context;
} @Override
public int getCount() {
return contactlist.size();
} @Override
public Object getItem(int position) {
return contactlist.get(position);
} @Override
public long getItemId(int position) {
return position;
} @Override
public View getView(final int position, View convertView, ViewGroup parent) {
View view;
if(convertView!=null){
view = View.inflate(context,R.layout.contact_item, null);
TextView name = (TextView) view.findViewById(R.id.tv_contact_item_name);
TextView number = (TextView) view.findViewById(R.id.tv_contact_item_number);
CheckBox cb = (CheckBox) view.findViewById(R.id.cb_check);
ContactInfo contact = contactlist.get(position);
name.setText(contact.getContactName());
number.setText(contact.getUserNumber());
cb.setChecked(contact.getChecked()); cb.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// TODO Auto-generated method stub
contactlist.get(position).setChecked(isChecked);
}
});
}else{
view = View.inflate(context,R.layout.contact_item, null);
TextView name = (TextView) view.findViewById(R.id.tv_contact_item_name);
TextView number = (TextView) view.findViewById(R.id.tv_contact_item_number);
CheckBox cb = (CheckBox) view.findViewById(R.id.cb_check);
ContactInfo contact = contactlist.get(position);
name.setText(contact.getContactName());
number.setText(contact.getUserNumber());
cb.setChecked(contact.getChecked());
cb.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// TODO Auto-generated method stub
contactlist.get(position).setChecked(isChecked);
}
});
} return view;
} }

这个就是选择联系人的页面,点击确定按钮则将联系人转化成json串当作字符串传过去

这里还有一个javabean,联系人信息

package com.xiaoxu.message.bean;

public class ContactInfo {
private String contactName;
private String userNumber;
private boolean isChecked; public String getContactName() {
return contactName;
}
public void setContactName(String contactName) {
this.contactName = contactName;
}
public String getUserNumber() {
return userNumber;
}
public void setUserNumber(String userNumber) {
this.userNumber = userNumber;
}
public boolean getChecked() {
return isChecked;
}
public void setChecked(boolean isChecked) {
this.isChecked = isChecked;
} }

已经可以了,不妨试一下吧。

这里面不涉及什么难点,如果遇到了问题,欢迎提问吧