利用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

[java]
/*
 * 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:
[java]
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:
[java]
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; 
    } 
 

 

摘自 tobacco5648的專欄

發佈留言