初识安卓之:异步备份手机短信,详解自定义接口,回调抽象方法
主界面中的代码如下:
//本工程主要分析了异步备份手机里所有短信得到sd卡上时,工具类中的工具方法通过回调主函数中定义的抽象方法,向主函数实时传递自己备份了多少条短信 //从而在主函数可以显示进度条的动态效果,需要的权限:READ_SMS;WRITE_SMS;WRITE_EXTERNAL_STORAGE //通过传递抽象对象的引用可以很好的解耦,使得工具方法只提供实时备份数据,主函数可以自由选择如何处理这些数据以便更好的呈现动态过程 public class MsgCopyToXMLActivity extends Activity { /** Called when the activity is first created. */ private ProgressDialog pd; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } public void copyMsg(View view){ try { File file = new File(Environment.getExternalStorageDirectory(),"smsbackup.xml"); FileOutputStream fos = new FileOutputStream(file); //AsyncTask<执行异步任务时所必须的参数(如果必须的话),异步任务执行的进度,异步任务执行完毕后的返回值(就是backgroud方法的返回值类型)>——————>这里这三个值只能写数据类型,不能写具体对象 new AsyncTask<OutputStream, Integer, Boolean>() { //后台执行的任务(所需参数的类型,可变参数数组(内含所需参数的值)) @Override protected Boolean doInBackground(OutputStream... params) { try { MsgCopyUtil smsUtils = new MsgCopyUtil(getApplicationContext()); //params[0]=fos=execute所接受的参数 //在后台任务中调用自定义的工具方法,该工具方法需要接受一个抽象类的对象(自己设计的抽象类) /** * 这里的第二个参数必须传一个自定义接口的对象,所以必须实现接口中的抽象方法才能创建出对象,相当于这里的这个对象是出生就 * 带着两个抽象方法的,把这个带着抽象方法的接口对象传给工具方法后,工具方法拿着传过来的这个接口对象想调用抽象方法, * 就只能用我们创建接口对象时已经实现好的方法,也就是说,它是借用的我们的抽象方法去办事,它自己没有,因为它自己没实现 * 这个借用我们的抽象方法的过程就叫做:回调,这种抽象方法就叫做回调函数。 * 比如:listener.beforeBackup(cursor.getCount());这句话就是用了我们实现好的方法,而且给我们的方法传进去了一个参数 * 它回调时传的参数,我们这边可以立马捕获,因为它的对象本来就是我们的对象的引用 * 要始终记得:我们把自定义接口类型的对象(带着两个方法)传递给工具类的方法后,工具方法拿着这个自定义接口类型对象的引用调用抽象方法时,调用的不是工具类 * 中的抽象方法体,而是借用的我们已经实现了的抽象方法去做事,它用我们的方法办事,我们这边当然都可以拿到 */ smsUtils.backUpSms(params[0],new MsgCopyUtil.BackUpProcessListener() { @Override public void onProcessUpdate(int process) { pd.setProgress(process); } @Override public void beforeBackup(int max) { pd.setMax(max); } }); return true; } catch (Exception e) { e.printStackTrace(); return false; } } //后台任务执行前的操作 @Override protected void onPreExecute() { pd = new ProgressDialog(MsgCopyToXMLActivity.this); pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); pd.setTitle("提示:"); pd.setMessage("正在备份短信...."); pd.show(); super.onPreExecute(); } //后台任务执行后的操作 @Override protected void onPostExecute(Boolean result) { pd.dismiss(); if(result){ Toast.makeText(getApplicationContext(), "备份成功", 0).show(); }else{ Toast.makeText(getApplicationContext(), "备份失败", 0).show(); } super.onPostExecute(result); } @Override protected void onProgressUpdate(Integer... values) { // TODO Auto-generated method stub super.onProgressUpdate(values); } }.execute(fos); } catch (Exception e) { e.printStackTrace(); Toast.makeText(getApplicationContext(), "备份失败..", 1).show(); } } }
工具类代码如下
public class MsgCopyUtil { private Context context; public MsgCopyUtil(Context context) { this.context = context; } public interface BackUpProcessListener{ void beforeBackup(int max); void onProcessUpdate(int process); } //后台执行的这个备份短信方法,除了接受一个输出流,还要提供一个接口,让调用者去选择自己想要的进度条样式,实现抽象方法, //这样,调用者一旦调用这些抽象方法,创建一个抽象对象后,由于抽象类是在这里定义的,new出来的对象引用指向这里的listener //相当于别处创建的对象通引用就遥控工具类的抽象对象了 public void backUpSms(OutputStream os, BackUpProcessListener listener) throws Exception{ Uri uri = Uri.parse("content://sms/"); XmlSerializer serializer = Xml.newSerializer(); serializer.setOutput(os, "utf-8"); serializer.startDocument("utf-8", true); serializer.startTag(null, "smss"); Cursor cursor = context.getContentResolver().query(uri, new String[]{"address","date","type","body"} , null, null, null); // listener.beforeBackup(cursor.getCount()); int total = 0; while(cursor.moveToNext()){ String address = cursor.getString(0); String date =cursor.getString(1); String type =cursor.getString(2); String body =cursor.getString(3); serializer.startTag(null, "sms"); serializer.startTag(null, "address"); serializer.text(address); serializer.endTag(null, "address"); serializer.startTag(null, "date"); serializer.text(date); serializer.endTag(null, "date"); serializer.startTag(null, "type"); serializer.text(type); serializer.endTag(null, "type"); serializer.startTag(null, "body"); serializer.text(body); serializer.endTag(null, "body"); serializer.endTag(null, "sms"); os.flush(); total++; listener.onProcessUpdate(total); } cursor.close(); serializer.endTag(null, "smss"); serializer.endDocument(); os.flush(); os.close(); } public void restoreSms(){ //读取xml文件. 把每一条短信的数据获取出来,插入到系统的数据库 } }