移动应用开发Android通讯录导入小工具

应用开发要求

这里写图片描述

系统运行效果

这里写图片描述

实现思路与设计

这里写图片描述

废话不多说,上代码

首先是MainActivity

package com.example.tsm.xmldemo;

import android.app.Dialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.Toast;

import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

public class MainActivity extends AppCompatActivity implements View.OnClickListener{

    private Button search,button_openfile;
    private ListView list;
    private ArrayList<Person> persons;
    //private SimpleAdapter mAdapter;
    private int [] tImg = new int[]{R.mipmap.ic_launcher_round,R.mipmap.ic_launcher_round,R.mipmap.ic_launcher_round,R.mipmap.ic_launcher_round,R.mipmap.ic_launcher_round};
    private String [] name = new String[10];
    private String [] phoneNumber = new String[10];
    private String [] temp = new String[3];
    private String filepath = null;

    static private int openfileDialogId = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setView();
    }

    private void  setView(){
        search = (Button) findViewById(R.id.search);
        list = (ListView) findViewById(R.id.list);
        button_openfile = (Button) findViewById(R.id.button_openfile);
        search.setOnClickListener(this);
        button_openfile.setOnClickListener(this);
    }

    private ArrayList<Person> readxmlForSAX() throws Exception {
        //获取文件资源建立输入流对象
        InputStream is = new FileInputStream(filepath);
        //①创建XML解析处理器
        SaxHelper ss = new SaxHelper();
        //②得到SAX解析工厂
        SAXParserFactory factory = SAXParserFactory.newInstance();
        //③创建SAX解析器
        SAXParser parser = factory.newSAXParser();
        //④将xml解析处理器分配给解析器,对文档进行解析,将事件发送给处理器
        parser.parse(is, ss);
        is.close();
        return ss.getPersons();
    }

    @Override
    protected Dialog onCreateDialog(int id) {
        if(id==openfileDialogId){
            Map<String, Integer> images = new HashMap<String, Integer>();
            // 下面几句设置各文件类型的图标, 需要你先把图标添加到资源文件夹
            images.put(OpenFileDialog.sRoot, R.drawable.filedialog_root);   // 根目录图标
            images.put(OpenFileDialog.sParent, R.drawable.filedialog_folder_up);    //返回上一层的图标
            images.put(OpenFileDialog.sFolder, R.drawable.filedialog_folder);   //文件夹图标
            images.put("xml",R.drawable.filedialog_file); //文件图标
            images.put("wav", R.drawable.filedialog_wavfile);   //wav文件图标
            images.put(OpenFileDialog.sEmpty, R.drawable.filedialog_root);
            Dialog dialog = OpenFileDialog.createDialog(id, this, "打开文件", new CallbackBundle() {
                        @Override
                        public void callback(Bundle bundle) {
                            filepath = bundle.getString("path");
                            Toast.makeText(getApplicationContext(),"选择成功!",Toast.LENGTH_LONG).show();
                            //setTitle(filepath); // 把文件路径显示在标题上
                        }
                    },
                    ".wav;.xml;",
                    images);
            return dialog;
        }
        return null;
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.search:
//                String path=getApplicationContext().getFilesDir().getAbsolutePath();
//                Toast.makeText(getApplicationContext(),filepath+"&&"+path,Toast.LENGTH_LONG).show();
//                //Log.i("XXXXQQQQ",filepath+"&&"+path);
                //Log.i("xxx","执行了1");
                try {
                    persons = readxmlForSAX();
                    //Log.i("xxx","执行了2");
                } catch (Exception e) {
                    e.printStackTrace();
                }
                //mAdapter = new ArrayAdapter<Person>(MainActivity.this, R.layout.list_item, persons);
                List<Map<String, Object>> listitem = new ArrayList<Map<String, Object>>();
                //Log.i("xxx","执行了3"+persons.get(0).toString()+","+ persons.size());

                for (int i=0;i< persons.size();i++){
                    temp = persons.get(i).toString().split(",");
                    name[i] = temp[0];
                    phoneNumber[i] = temp[1];
                }
                for (int i = 0; i < persons.size() ; i++){
                    Map<String,Object> showitem = new HashMap<String, Object>();
                    showitem.put("name",name[i]);
                    //Log.i("name"+i,name[i]);
                    showitem.put("phoneNumber",phoneNumber[i]);
                    showitem.put("tImg",tImg[i]);
                    listitem.add(showitem);
                }
                SimpleAdapter mAdapter = new SimpleAdapter(getApplicationContext(),listitem , R.layout.list_item ,new String[]{"tImg","name","phoneNumber"},new int[]{R.id.imageView,R.id.name,R.id.phoneNumber});
                list.setAdapter(mAdapter);
                Toast.makeText(getApplicationContext(),"导入成功!",Toast.LENGTH_LONG).show();
                break;
            case R.id.button_openfile:
                showDialog(openfileDialogId);
                break;

        }

    }
}

通讯录对象属性存储类
person

package com.example.tsm.xmldemo;

/**
 * Created by TSM on 2017/4/29.
 */

public class Person {
    private int id;
    private String name;
    private String phoneNumber;

    public Person(int id, String name, String phoneNumber) {
        this.id = id;
        this.name = name;
        this.phoneNumber = phoneNumber;
    }

    public Person() {
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }

    @Override
    public String toString() {
        return this.name + "," + this.phoneNumber;
    }
}

使用SAX方式解析XML文档
SaxHelper

package com.example.tsm.xmldemo;

import android.util.Log;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import java.util.ArrayList;

/**
 * Created by TSM on 2017/4/29.
 */

public class SaxHelper extends DefaultHandler {
    private Person person;
    private ArrayList<Person> persons;
    //当前解析的元素标签
    private String tagName = null;

    /**
     * 当读取到文档开始标志是触发,通常在这里完成一些初始化操作
     */
    @Override
    public void startDocument() throws SAXException {
        this.persons = new ArrayList<Person>();
        //Log.i("SAX", "读取到文档头,开始解析xml");
    }


    /**
     * 读到一个开始标签时调用,第二个参数为标签名,最后一个参数为属性数组
     */
    @Override
    public void startElement(String uri, String localName, String qName,
                             Attributes attributes) throws SAXException {
        if (localName.equals("person")) {
            person = new Person();
            person.setId(Integer.parseInt(attributes.getValue("id")));
            //Log.i("SAX", "开始处理person元素~");
        }
        this.tagName = localName;
    }


    /**
     * 读到到内容,第一个参数为字符串内容,后面依次为起始位置与长度
     */

    @Override
    public void characters(char[] ch, int start, int length)
            throws SAXException {
        //判断当前标签是否有效
        if (this.tagName != null) {
            String data = new String(ch, start, length);
            //读取标签中的内容
            if (this.tagName.equals("name")) {
                this.person.setName(data);
                //Log.i("SAX", "处理name元素内容");
            } else if (this.tagName.equals("phoneNumber")) {
                this.person.setPhoneNumber(data);
                //Log.i("SAX", "处理age元素内容");
            }

        }

    }

    /**
     * 处理元素结束时触发,这里将对象添加到结合中
     */
    @Override
    public void endElement(String uri, String localName, String qName)
            throws SAXException {
        if (localName.equals("person")) {
            this.persons.add(person);
            person = null;
            //Log.i("SAX", "处理person元素结束~");
        }
        this.tagName = null;
    }

    /**
     * 读取到文档结尾时触发,
     */
    @Override
    public void endDocument() throws SAXException {
        super.endDocument();
        //Log.i("SAX", "读取到文档尾,xml解析结束");
    }

    //获取persons集合
    public ArrayList<Person> getPersons() {
        return persons;
    }

}

现在开始写打开弹出框选择文件的代码了
OpenFileDialog

package com.example.tsm.xmldemo;

/**
 * Created by TSM on 2017/4/29.
 */

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.Toast;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class OpenFileDialog {
    public static String tag = "OpenFileDialog";
    static final public String sRoot = "/";
    static final public String sParent = "..";
    static final public String sFolder = ".";
    static final public String sEmpty = "";
    static final private String sOnErrorMsg = "No rights to access!";

    // 参数说明
    // context:上下文
    // dialogid:对话框ID
    // title:对话框标题
    // callback:一个传递Bundle参数的回调接口
    // suffix:需要选择的文件后缀,比如需要选择wav、mp3文件的时候设置为".wav;.mp3;",注意最后需要一个分号(;)
    // images:用来根据后缀显示的图标资源ID。
    //  根目录图标的索引为sRoot;
    //  父目录的索引为sParent;
    //  文件夹的索引为sFolder;
    //  默认图标的索引为sEmpty;
    //  其他的直接根据后缀进行索引,比如.wav文件图标的索引为"wav"
    public static Dialog createDialog(int id, Context context, String title, CallbackBundle callback, String suffix, Map<String, Integer> images){
        AlertDialog.Builder builder = new AlertDialog.Builder(context);
        builder.setView(new FileSelectView(context, id, callback, suffix, images));
        Dialog dialog = builder.create();
        //dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
        dialog.setTitle(title);
        return dialog;
    }

    static class FileSelectView extends ListView implements OnItemClickListener{


        private CallbackBundle callback = null;
        private String path = sRoot;
        private List<Map<String, Object>> list = null;
        private int dialogid = 0;

        private String suffix = null;

        private Map<String, Integer> imagemap = null;

        public FileSelectView(Context context, int dialogid, CallbackBundle callback, String suffix, Map<String, Integer> images) {
            super(context);
            this.imagemap = images;
            this.suffix = suffix==null?"":suffix.toLowerCase();
            this.callback = callback;
            this.dialogid = dialogid;
            this.setOnItemClickListener(this);
            refreshFileList();
        }

        private String getSuffix(String filename){
            int dix = filename.lastIndexOf('.');
            if(dix<0){
                return "";
            }
            else{
                return filename.substring(dix+1);
            }
        }

        private int getImageId(String s){
            if(imagemap == null){
                return 0;
            }
            else if(imagemap.containsKey(s)){
                return imagemap.get(s);
            }
            else if(imagemap.containsKey(sEmpty)){
                return imagemap.get(sEmpty);
            }
            else {
                return 0;
            }
        }

        private int refreshFileList()
        {
            // 刷新文件列表
            File[] files = null;
            try{
                files = new File(path).listFiles();
            }
            catch(Exception e){
                files = null;
            }
            if(files==null){
                // 访问出错
                Toast.makeText(getContext(), sOnErrorMsg,Toast.LENGTH_SHORT).show();
                return -1;
            }
            if(list != null){
                list.clear();
            }
            else{
                list = new ArrayList<Map<String, Object>>(files.length);
            }

            // 用来先保存文件夹和文件夹的两个列表
            ArrayList<Map<String, Object>> lfolders = new ArrayList<Map<String, Object>>();
            ArrayList<Map<String, Object>> lfiles = new ArrayList<Map<String, Object>>();

            if(!this.path.equals(sRoot)){
                // 添加根目录 和 上一层目录
                Map<String, Object> map = new HashMap<String, Object>();
                map.put("name", sRoot);
                map.put("path", sRoot);
                map.put("img", getImageId(sRoot));
                list.add(map);

                map = new HashMap<String, Object>();
                map.put("name", sParent);
                map.put("path", path);
                map.put("img", getImageId(sParent));
                list.add(map);
            }

            for(File file: files)
            {
                if(file.isDirectory() && file.listFiles()!=null){
                    // 添加文件夹
                    Map<String, Object> map = new HashMap<String, Object>();
                    map.put("name", file.getName());
                    map.put("path", file.getPath());
                    map.put("img", getImageId(sFolder));
                    lfolders.add(map);
                }
                else if(file.isFile()){
                    // 添加文件
                    String sf = getSuffix(file.getName()).toLowerCase();
                    if(suffix == null || suffix.length()==0 || (sf.length()>0 && suffix.indexOf("."+sf+";")>=0)){
                        Map<String, Object> map = new HashMap<String, Object>();
                        map.put("name", file.getName());
                        map.put("path", file.getPath());
                        map.put("img", getImageId(sf));
                        lfiles.add(map);
                    }
                }
            }

            list.addAll(lfolders); // 先添加文件夹,确保文件夹显示在上面
            list.addAll(lfiles);    //再添加文件


            SimpleAdapter adapter = new SimpleAdapter(getContext(), list, R.layout.filedialogitem, new String[]{"img", "name", "path"}, new int[]{R.id.filedialogitem_img, R.id.filedialogitem_name, R.id.filedialogitem_path});
            this.setAdapter(adapter);
            return files.length;
        }
        @Override
        public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
            // 条目选择
            String pt = (String) list.get(position).get("path");
            String fn = (String) list.get(position).get("name");
            if(fn.equals(sRoot) || fn.equals(sParent)){
                // 如果是更目录或者上一层
                File fl = new File(pt);
                String ppt = fl.getParent();
                if(ppt != null){
                    // 返回上一层
                    path = ppt;
                }
                else{
                    // 返回更目录
                    path = sRoot;
                }
            }
            else{
                File fl = new File(pt);
                if(fl.isFile()){
                    // 如果是文件
                    ((Activity)getContext()).dismissDialog(this.dialogid); // 让文件夹对话框消失

                    // 设置回调的返回值
                    Bundle bundle = new Bundle();
                    bundle.putString("path", pt);
                    bundle.putString("name", fn);
                    // 调用事先设置的回调函数
                    this.callback.callback(bundle);
                    return;
                }
                else if(fl.isDirectory()){
                    // 如果是文件夹
                    // 那么进入选中的文件夹
                    path = pt;
                }
            }
            this.refreshFileList();
        }
    }
}

接口:CallbackBundle

package com.example.tsm.xmldemo;

import android.os.Bundle;

/**
 * Created by TSM on 2017/4/29.
 */

public interface CallbackBundle {
    abstract void callback(Bundle bundle);
}

好了,处理的工作写完啦,现在开始写界面代码了
activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_height="match_parent"
    android:layout_width="match_parent"
    android:orientation="vertical"
    android:layout_margin="10dp">

    <Button
        android:id="@+id/search"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/search"/>

    <Button
        android:id="@+id/button_openfile"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/diag"/>

    <ListView
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp">

    </ListView>
</LinearLayout>

filedialogitem.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/vw1"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:background="#000000"
    android:orientation="horizontal"
    android:padding="4dp" >


    <ImageView
        android:id="@+id/filedialogitem_img"
        android:layout_width="32dp"
        android:layout_height="32dp"
        android:layout_margin="4dp"/>

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical" >

        <TextView
            android:id="@+id/filedialogitem_name"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:textColor="#FFFFFF"
            android:textSize="18sp"
            android:textStyle="bold" />


        <TextView
            android:id="@+id/filedialogitem_path"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:paddingLeft="10dp"
            android:textColor="#FFFFFF"
            android:textSize="14sp" />

    </LinearLayout>

</LinearLayout>

list_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="15dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_marginBottom="5dp"
        >

        <ImageView
            android:id="@+id/imageView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:srcCompat="@mipmap/ic_launcher_round" />

        <TextView
            android:id="@+id/name"
            android:layout_width="80dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginLeft="20dp"
            android:textColor="@color/colorfont"
            android:text="姓名"/>

        <TextView
            android:id="@+id/phoneNumber"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:textColor="@color/colorfont"
            android:text="17673116337"/>
    </LinearLayout>
</LinearLayout>

用于解析的xml文件,把文件置于Android系统的mnt/sdcard文件夹下吧
person.xml

<?xml version="1.0" encoding="UTF-8"?>
<persons>
    <person id = "1">
        <name>沙瑞金</name>
        <phoneNumber>17673156987</phoneNumber>
    </person>
    <person id = "2">
        <name>赵东来</name>
        <phoneNumber>13008965489</phoneNumber>
    </person>
    <person id = "3">
        <name>刘大</name>
        <phoneNumber>15276321254</phoneNumber>
    </person>
    <person id = "4">
        <name>侯亮平</name>
        <phoneNumber>18963985236</phoneNumber>
    </person>
    <person id = "5">
        <name>高育良</name>
        <phoneNumber>17584563215</phoneNumber>
    </person>
</persons>

效果图展示:
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值