一. 分析 : java文件以及要实现的功能
1 .主界面------MainActivity.java
各个功能的跳转
MainActivity --------->ExportExcel.java (导出联系人)
---------->ImportExcel.java (导入联系人)
两个分支里面都 有文件浏览功能
------------>FileSerach.java (文件浏览)
2. 导出联系人界面 --------ExportExcel.java
功能有:
(1) 通过 ContentProvider 查询所有的联系人数据到 Cursor中。
(2) 将Cursor中的数据遍历并保存在 Map中,因为Cursor存在 的时间很短,我们无法保证 在很短的时间内完成所有 数据 的写入工作。
(3)遍历Map数据 并写入到Excel中。
3. 导入联系人 -----------ImportExcel.java
功能与导出相仿,主要 工作:
遍历Excel文件,将数据逐一写入到联系人数据库中。
4. 实现 文件的浏览功能模块---------FileSerach.java
用于浏览手机中所有 的文件,以方便用户选择要导入 or导出的路径。
二、先重点实现导出联系人界面的所功能
整体设计
initView() --------------->initXLs() ---------------> add()
public class ExportExcel extends Activity{ public String FILE_PATH =""; public String FILE_NAME=""; public static final String END_TAG="导出完毕,可以退出程序"; WritableWorkbook wwb ; WritableSheet ws; ContentResolver resolver ; TextView tv; TextView tips ; EditText fileNameEdit; EditText filePathEdit; Button searchBtn; Button exportBtn; ProgressBar bar; Handler handler ; //Handler用于处理消息,改变 UI HashMap <String ,String >map = new HashMap<String ,String >();//保存联系人信息 HashMap<String ,String >new_map= new HashMap<String ,String >(); //保存已经导出的联系人数据 @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); this.setContentView(R.layout.export); initView(); handler = new Handler (){ public void handleMessage(Message msg) { String content =(String) msg.obj; int added= msg.arg1; tv.setText(content); //显示正在导出的人名 bar.setProgress(added); //进度 if(content.equals(END_TAG)){ bar.setVisibility(View.INVISIBLE); tips.setVisibility(View.INVISIBLE); tv.append("\n本次导出记录 :"+String.valueOf(added)+"条"); } super.handleMessage(msg); } }; } private void initView() { // TODO Auto-generated method stub } }
在安卓 中,所有界面的更新都要在主线程中,如果我们希望在不同的线程中更新UI,可以使用Handler ,在安卓 中,Handler常常用来接收其它线程发送的消息,并适时进行界面的更新。
Handler是一个用于线程间通信的类,最常用于做下载条,
我们重写 handleMessage方法,并在这个 方法中进行界面的更新,在其它的线程中使用
Handler.sendMessage ()
方法就可以触发这个 回调方法。
2. initView的实现
private void initView() { // TODO Auto-generated method stub tv = (TextView)findViewById(R.id.tv); tips=(TextView)findViewById(R.id.tips); fileNameEdit=(EditText)findViewById(R.id.fileNameEdit); filePathEdit=(EditText)findViewById(R.id.filePathEdit); searchBtn =(Button)findViewById(R.id.search); exportBtn =(Button)findViewById(R.id.exportBtn); bar =(ProgressBar )findViewById(R.id.bar); tips.setVisibility(View.INVISIBLE); //先不可见 bar.setVisibility(View.INVISIBLE); tv.setVisibility(View.INVISIBLE); searchBtn.setOnClickListener(new OnClickListener(){ public void onClick(View arg0) { Intent i = new Intent (getBaseContext() , FileSearch.class); startActivityForResult(i ,0); //requestCode } }); exportBtn.setOnClickListener(new OnClickListener(){ public void onClick(View v) { // TODO Auto-generated method stub map.clear(); new_map.clear(); FILE_NAME=fileNameEdit.getText().toString(); //得到文件名 FILE_PATH=filePathEdit.getText().toString(); //文件路径 if (initXLs()){ //初始化jxl,使之可用,如果成功,则开始添加 bar.setMax(map.size()); //这是 用map,而不是new_map tips.setVisibility(View.VISIBLE); bar.setVisibility(View.VISIBLE); tv.setVisibility(View.VISIBLE); Thread th = new Thread(new Runnable(){ public void run() { // TODO Auto-generated method stub add(); //使用单独的线程完成 将联系人添加 到excel的工作 } }); th.start(); } } }); }
3. initXLs的实现
功能 :实现 了可写 的workbook和sheet的创建 ,同时 完成 了数据 源了组成 ,也就是将联系人列表读入HashMap中。
private boolean initXLs() { // TODO Auto-generated method stub if(FILE_PATH.trim().equals("")){ FILE_PATH= Environment.getExternalStorageDirectory().getAbsolutePath(); } if (!FILE_NAME.endsWith(".xls")&&!FILE_NAME.contains(".")){ FILE_NAME=FILE_NAME+".xls"; } String path = FILE_PATH+"/"+FILE_NAME.trim(); try{ File file = new File(path); if(!file.exists()){ file.createNewFile(); } wwb=Workbook.createWorkbook(file); ws = wwb.createSheet("联系人列表",0); //得到ContentResolver对象 resolver=getContentResolver(); Cursor cursor = resolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null); cursor.moveToFirst(); while (!cursor.isAfterLast()){ String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)); //得到姓名 String number = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)); map.put(name, number); cursor.moveToNext(); } return true; }catch(FileNotFoundException e){ e.printStackTrace(); }catch(IOException e1){ Toast.makeText(getBaseContext(), "文件路径错误", Toast.LENGTH_SHORT).show(); e1.printStackTrace(); } return false; }
注意,里面用到了IO相关的类,要给一定的权限 ,要不然会出现 IOException.
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.WRITE_CONTACTS"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
如果在Workbook创建 时,出现 了找不到Class的错误 ,应该是jxl 库导入的问题,可以直接复制 到libs文件下。
注意里面的联系人信息的取得 :
联系人列表 URI:
ContactsContract.CommonDataKinds.Phone.CONTENT_URI
联系人姓名:
ContactsContract.Contacts.DISPLAY_NAME
联系人电话:
ContactsContract.CommonDataKinds.Phone.NUMBER
4. add的实现
由于 add()方法执行在不同的线程中,所以我们不能直接 在这个 线程中进行UI的修改,这就要用来 我们讲到的
Handler.sendMessage()方法。
private void add() { // TODO Auto-generated method stub try { Iterator <Entry<String ,String >>iter = map.entrySet().iterator(); Label labelC0= new Label (0 ,0 ,"name"); Label labelC1 = new Label (1,0,"number"); ws.addCell(labelC0); ws.addCell(labelC1); int row =1; while (iter!=null&&iter.hasNext()){ //遍历Map Entry <String ,String >entry = iter.next(); String name = entry.getKey(); String number =entry.getValue(); //判断 是否有重复的 if(map_new.containsKey(number)){ continue; }else { map_new.put(number, ""); } //将姓名 和号码写入到单元 格并加入 到表中,同时 能和 handler此时 正在 导出的内容 if(name!=""&&number!=""){ Label labelName = new Label (0,row, name); Label labelNumber = new Label (1,row ,number ); ws.addCell(labelName); ws.addCell(labelNumber); Message msg = new Message (); msg.obj= name+":"+number ; msg.arg1= row; handler.sendMessage(msg); //消息发送到handler 中 row++; } } wwb.write(); //写入到wwb中 wwb.close(); Message msg = new Message (); //发送结束标志 msg.obj=END_TAG; msg.arg1=row-1; handler.sendMessage(msg); }catch(Exception e ){ e.printStackTrace(); } }
为了加入延时的效果,我们在row++代码 后面加入 线程延时600ms
try { Thread.currentThread().sleep(600); } catch (InterruptedException e) { e.printStackTrace(); }
5. 实现 onActivityResult()方法
由于在整体设计 中,我们用到了startActivityForResult (),所以有这个。
protected void onActivityResult(int requestCode, int resultCode, Intent data) { // TODO Auto-generated method stub super.onActivityResult(requestCode, resultCode, data); switch(resultCode){ case RESULT_OK: Bundle bundle = data.getExtras(); String filePath = bundle.getString("filePath"); filePathEdit.setText(filePath); break; default : break; } }