利用ListActivity,CursorAdapter获取用户输入(短信群发器的地址输入实现)总结


    这两天在做一个短信群发器,在用ListActivity和CursorAdapter罗列联系人并记录用户输入时遇到了一些麻烦,解决过程颇为繁琐,深深感到Android API之广、杂的同时也让自己能静下心来谨慎编码仔细调试广泛查阅,现将最终成果和各种问题以及相应解决方法一一罗列,作为这两日的工作总结的同时,希望能给各位带来一些帮助。

    先说明下这个模块要实现的功能吧,此模块主要为群发短信的地址输入模块,用户可以在EditText中直接输入地址,也可以从联系人中pick多个电话号码。

    遇到的主要问题有:

    1.为了实现两种输入方式(直接EditText输入和联系人选择输入),创建了一个从联系人选择电话号码的ListActivity,为了能在地址编辑Activity和ListActivity之间切换而不丢失已经编辑了的电话号码,就得创建一种数据结构来保存这些电话号码,我这里使用的是一个LinkedList(具体结构后面再阐述),但是怎么样才能保证每次切换都能正确保存地址数据而且EditText内容与地址数据结构保持一致呢?!解决方法是在每次Activity切换时都先进行一次解析或提取过程:从EditText切换到ListActivity之前读取EditText的字符串内容并分析获得地址数据保存到LinkedList中,从ListActivity切换到Activity之前解析LinkedList内容获取要在EditText中显示的字符串内容。

    2.有些联系人的号码不止一个,那么应该如何对待?这里我选择的方式和我的Android 2.3系统自带的短信发送器不一样,系统自带的在从联系人获取号码时,如果联系人的号码多于1个,会弹出一个对话框让用户选择一个号码,而我选择的时对话框让用户选择多个号码。

    3.对话框与主Activity之间的通信问题,如何让对话框保存用户选择给Activity使用?这里我的解决方式是用静态变量和final变量,从内部类中调用这些变量。

    4.用户从对话框选择号码后,如何更新ListActivity的显示内容?我的解决方法是用Handler,对话框给Handler发送消息,Handler使ListActivity更新界面,更新方法为调用Cursor的requery方法。

    还有几个比较小的问题,比如联系人数据库的内容,ListActivity中CheckBox的绘制等,就不一一列举了。

    现附上我的代码(代码上还有很多清晰的改动以及调试痕迹,呵呵):

a.短信编辑Activity


/*
 * this Activity is created for sending message
 * users would edit sms message body in the EditText message , and destinations in the EditText receivers
 * there can be more than one destinations , and they are arranged at a strict layout
 * the phone number of every destination would be a String of digits , and they are separated by ','
 * and the spaces in the string are all ignored
 * a valid destinations description is like this : 1234 ,1254,1 3 52,6528,
 * 
 */
package com.tobacco.activity;

import java.util.ArrayList;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;

import com.tobacco.pro.R;
import com.tobacco.sms.SMSSender;

public class EditMessAct extends Activity implements OnClickListener{
	private Button findContacts;
	private Button send;
	private EditText receivers;
	private EditText message;
	private ArrayList<String> dest;
	private static final char SEPARATE=',';
	@Override
	public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.editmessage);
        init();
    }
	private void init(){
		findContacts=(Button)findViewById(R.id.contacts);
		send=(Button)findViewById(R.id.send);
		receivers=(EditText)findViewById(R.id.receivers);
		message=(EditText)findViewById(R.id.messagetext);
		findContacts.setOnClickListener(this);
		send.setOnClickListener(this);
		dest=new ArrayList<String>();
	}
	@Override
	public void onClick(View v) {
		// TODO Auto-generated method stub
		Intent i;
		if(v==findContacts){
			refreshDest();
			i=new Intent(this,ListContactAct.class);
			this.startActivityForResult(i,1);
		}
		else if(v==send){
			refreshDest();
			String t=message.getText().toString();
			new SMSSender(t,dest).send();
		}
		
	}
	
	@Override
    protected void onActivityResult(int request,int result,Intent intent){
    	super.onActivityResult(request,result,intent);
    	int t=ListContactAct.selectedReceiver.size();
    	int i=0;
    	int k=0;
    	int p,j;
    	boolean mark;
    	//String str="";
    	for(i=0;i<t;i++){
    		//str=str+ListContactAct.selectedReceiver.get(i).phoneNumber+";";
    		p=ListContactAct.selectedReceiver.get(i).phoneNumber.size();
    		for(k=0;k<p;k++){
    			mark=true;
    			for(j=0;j<dest.size();j++){
    				if(ListContactAct.selectedReceiver.get(i).phoneNumber.get(k).equals(dest.get(j))){
    					mark=false;
    				}
    			}
    			if(mark){
    				dest.add(ListContactAct.selectedReceiver.get(i).phoneNumber.get(k));
    			}
    		}
    	}
    	refreshText();
    	//receivers.setText(str+receivers.getText().toString());
    }
	//refresh the EditText receivers by the ArrayList dest
	private void refreshText(){
		String t="";
		int k=dest.size();
		int i;
		for(i=0;i<k;i++){
			t+=dest.get(i);
			t+=SEPARATE;
		}
		receivers.setText(t);
	}
	//refresh the ArrayList dest by the EditText receivers and return information of the analyze result
	private int refreshDest(){
		ArrayList<String> tempDest=new ArrayList<String>();
		String f=receivers.getText().toString();
		int k=f.length();
		String number="";
		for(int i=0;i<k;i++){
			if(f.charAt(i)==SEPARATE){
				if(number.length()>0){
					boolean tempMark=true;
					for(int m=0;m<tempDest.size();m++){
						if(tempDest.get(m).equals(number)){
							tempMark=false;
							break;
						}
					}
					if(tempMark){
						tempDest.add(number);
					}
					
				}
				number="";
			}
			else if(f.charAt(i)>='0'&&f.charAt(i)<='9'){
				number+=f.charAt(i);
			}
		}
		if(number.length()>0){
			boolean tempMark=true;
			for(int m=0;m<tempDest.size();m++){
				if(tempDest.get(m).equals(number)){
					tempMark=false;
					break;
				}
			}
			if(tempMark){
				tempDest.add(number);
			}
			
		}
		dest=tempDest;
		return 0;
	}

}

从联系人pick号码的ListActivity:

package com.tobacco.activity;

//import java.util.ArrayList;
import java.util.ArrayList;
import java.util.LinkedList;

import android.app.AlertDialog;
import android.app.ListActivity;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.provider.ContactsContract;
import android.provider.Contacts.People.Phones;
import android.util.Log;
import android.view.View;
import android.widget.CheckBox;
import android.widget.ListView;

import com.tobacco.adapter.ListContactsAdapter;
import com.tobacco.pro.R;
import com.tobacco.types.Receiver;

@SuppressWarnings("deprecation")
public class ListContactAct extends ListActivity{
	private Cursor cursor;
	public static LinkedList<Receiver> selectedReceiver;
	public static LinkedList<Integer> selectedPos;
	private int idColumn;
	private int displayNameColumn;
	public static Handler hand;
	//private Cursor phones=null;
	//private ArrayList<String> pNumber;
	@Override
	public void onCreate(Bundle savedInstanceState){
		super.onCreate(savedInstanceState);
		//pNumber=new ArrayList<String>();
		selectedReceiver =new LinkedList<Receiver>();
		selectedPos=new LinkedList<Integer>();
		//cursor=getContentResolver().query(People.CONTENT_URI,null,null,null,null);
		//the cursor get by the above command has no column of has_phone_number
        cursor= managedQuery(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
		debugColumnInfo();
		startManagingCursor(cursor);
		idColumn=cursor.getColumnIndex(ContactsContract.Contacts._ID);
		displayNameColumn=cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
		ListContactsAdapter adapter = new ListContactsAdapter(
                this,
                R.layout.listcontact,
                cursor,
                new String[] {Phones.DISPLAY_NAME},
                new int[] {R.id.people});
		this.setListAdapter(adapter);
		hand=new Handler(){
			@Override
			public void handleMessage(Message msg){
				Bundle bundle=msg.getData();
				int pos=bundle.getInt("position");
				if(pos!=-1){
					cursor.requery();
				}
			}
		};
	}
	@Override
	protected void onPause(){
		super.onPause();
		Intent intent=new Intent();
		intent.putExtra("date",1);
		setResult(1,intent);
		finish();
	}
	@Override
	protected void onListItemClick (ListView l, View v, int position, long id){
		//Toast.makeText(this,""+position+"+"+id,Toast.LENGTH_SHORT).show();
		CheckBox cbx = (CheckBox) v.findViewById(R.id.check);
		String contactId=null;
		String displayName=null;
		int hasPhone;
		final int phoneCount;
		int t=0;
		int q=0;
		int i;
		
		cursor.moveToPosition(position);
		contactId=cursor.getString(idColumn);
		displayName = cursor.getString(displayNameColumn);
		while(q<selectedReceiver.size()&&!selectedReceiver.get(q).id.equals(contactId)){
			q++;
		}
		Integer intg=new Integer(position);
		while(t<selectedPos.size()&&!selectedPos.get(t).equals(intg)){
			t++;
		}
		
		
		if(t<selectedPos.size()){
			if(cbx.isChecked()){
				cbx.setChecked(false);
			}
			selectedReceiver.remove(q);
			selectedPos.remove(t);
			//the people has been added to the send list already
			/*phoneCount=cursor.getInt(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER));
			if(phoneCount>1){
				a
			}*/
		}
		else{
			//the people has not been added to the send list yet
			hasPhone=Integer.parseInt(cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER)));
			//note:the variable hasPhone ,as the number stored in column has_phone_number is not represent the count of
			//phone numbers the people has,but the mark that if the people has at least one phone number ,1 has or 0 not
			//Toast.makeText(this,"phoneCount:"+phoneCount,Toast.LENGTH_SHORT).show();
			
			if(hasPhone>0){
				final Cursor phones = getContentResolver().query(
						ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
						null,
						ContactsContract.CommonDataKinds.Phone.CONTACT_ID
						+ " = " + contactId, null, null);
				//Toast.makeText(this,"phoneCount22:"+phones.getCount(),Toast.LENGTH_SHORT).show();
				phoneCount=phones.getCount();
				final String[] pNums=new String[phoneCount];
				//pNumber=new ArrayList<String>();
				if (phones.moveToFirst()){
					i=0;
					do{
						//pNumber.add(phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)));
						//pNumber is a ArrayList instance to record the phone numbers of the people that was clicked
						pNums[i]=phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
						i++;
					}while (i<phoneCount&&phones.moveToNext());
				}
				//Toast.makeText(this,""+pNumber.get(0),Toast.LENGTH_SHORT).show();
				
				if(phoneCount==1){
					if(!cbx.isChecked()){
						cbx.setChecked(true);
					}
					selectedReceiver.add(new Receiver(contactId,displayName,pNums[0]));
					Integer in=new Integer(position);
					selectedPos.add(in);
				}
				else if(phoneCount>1){
					final boolean[] mark=new boolean[phoneCount];
					final String name=displayName;
					final int p=position;
					final String conId=contactId;
					for(int w=0;w<phoneCount;w++){
						mark[w]=false;
					}
					AlertDialog ad=new AlertDialog.Builder(this)
					.setTitle("select phone number")
					.setMultiChoiceItems(pNums,mark,new DialogInterface.OnMultiChoiceClickListener(){
						public void onClick(DialogInterface dialog,int which,boolean isChecked){
							
						}
					})
					.setPositiveButton("okay",new DialogInterface.OnClickListener(){
						public void onClick(DialogInterface dialog,int which){
							ArrayList<String> a=new ArrayList<String>();
							for(int u=0;u<mark.length;u++){
								if(mark[u]){
									a.add(pNums[u]);
								}
							}
							ListContactAct.selectedReceiver.add(new Receiver(conId,name,a));
							Integer in=new Integer(p);
							ListContactAct.selectedPos.add(in);
							Bundle bundle=new Bundle();
							bundle.putInt("position",p);
							Message msg=Message.obtain();
							msg.setData(bundle);
							ListContactAct.hand.sendMessage(msg);
						}
					}).setNegativeButton("cancel",null).create();
					ad.show();
				}
				
			}
		}
		
		super.onListItemClick(l, v, position, id);
		
	}
	
	private void debugColumnInfo(){
		int count=cursor.getColumnCount();
		int t=0;
		String tag="DebugColumn";
		for(;t<count;t++){
			Log.d(tag,cursor.getColumnName(t));
		}
	}

}

自定义Adapter:

package com.tobacco.adapter;

import com.tobacco.activity.ListContactAct;
import com.tobacco.pro.R;

import android.content.Context;
import android.database.Cursor;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.SimpleCursorAdapter;

public class ListContactsAdapter extends SimpleCursorAdapter{

	public ListContactsAdapter(Context context, int layout, Cursor c,String[] from, int[] to) {
		super(context, layout, c, from, to);
	}
	
	@Override
	public View getView(int position, View convertView, ViewGroup parent){
		View rowView=super.getView(position,convertView,parent);
		int t=0;
		Integer in=new Integer(position);
		while(ListContactAct.selectedPos.size()>t&&!ListContactAct.selectedPos.get(t).equals(in)){
			t++;
		}
		CheckBox cbx=(CheckBox)(rowView.findViewById(R.id.check));
		if(t<ListContactAct.selectedPos.size()){
			cbx.setChecked(true);
		}
		else
		{
			cbx.setChecked(false);
		}
		return rowView;
	}

}



你可能感兴趣的:(数据结构,String,null,Integer,button,Numbers)