Android傳送簡訊(簡訊傳送以及群發和從電話本選擇聯絡人)---簡訊管家2
阿新 • • 發佈:2019-02-17
分析下怎麼寫
首先,我們需要一個輸入框,可以手動的輸入手機號碼,
其次,很少有人願意手動輸入,那麼我們需要提供一個按鈕來給我們的使用者選擇自己電話本中的聯絡人(一次可以選擇多個即群發)
然後,我們需要一個簡訊編輯介面,可以編輯簡訊
最後兩個按鈕,一個傳送,點選後傳送訊息,一個取消(取消後存為草稿,目前沒有開發)
這個是我的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>
然後點選那個小人按鈕,我們需要載入聯絡人如下圖:
目前寫了一個全部聯絡人,當然支援從手機聯絡人選擇和sim卡選擇問題也不大的
模擬器上聯絡人比較少。
選擇聯絡人以後,點選確認,會自動將聯絡人填寫到傳送簡訊頁面的電話號碼那個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;
}
}
已經可以了,不妨試一下吧。
這裡面不涉及什麼難點,如果遇到了問題,歡迎提問吧