all2

package com.example.sharingcontact.db;

import java.io.Serializable;

import android.provider.ContactsContract.FullNameStyle;

public class ContactInfo implements Serializable{
	public int ContactID = 0;		// 联系人ID号
	public String Name = null;		// 姓名
	public String SubName = null;	// 昵称
	public String MobileTel = null;	// 移动电话
	public String FixedTel = null;	// 固定电话
	public String Company = null;	// 单位
	public String Address = null;	// 住址
	public int ImageId = 0;			// 图id
	
	public ContactInfo(String name, String subName, String mobileTel, String fixedTel, String company, String address, int imageId){
		Name = name;
		SubName = subName;
		MobileTel = mobileTel;
		FixedTel = fixedTel;
		Company = company;
		Address = address;
		ImageId = imageId;
	}
	public ContactInfo(){
	}	
	
	public String getSortKey(ContactInfo info){
		String Sort_Key = ContactLocaleUtils.getIntance().getSortKey(info.Name, FullNameStyle.CHINESE);
		
		return Sort_Key;
	}
	
	public String getPinyin(ContactInfo info){
		String Pinyin = ContactLocaleUtils.getIntance().getPinYin(info.Name);
		
		return Pinyin;
	}
	
	public String getFisrtPinyin(ContactInfo info){
		String FisrtPinyin = ContactLocaleUtils.getIntance().getFirstPinYin(info.Name);
		
		return FisrtPinyin;
	}
	
}



/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License
 */

package com.example.sharingcontact.db;

import android.provider.ContactsContract.FullNameStyle;
import android.util.SparseArray;

import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Locale;

import com.example.sharingcontact.db.HanziToPinyin.Token;

/**
 * This utility class provides customized sort key and name lookup key according the locale.
 */
public class ContactLocaleUtils {

    /**
     * This class is the default implementation.
     * <p>
     * It should be the base class for other locales' implementation.
     */
    public class ContactLocaleUtilsBase {
        public String getSortKey(String displayName) {
            return displayName;
        }
        @SuppressWarnings("unused")
        public Iterator<String> getNameLookupKeys(String name) {
            return null;
        }
    }

    /**
     * The classes to generate the Chinese style sort and search keys.
     * <p>
     * The sorting key is generated as each Chinese character' pinyin proceeding with
     * space and character itself. If the character's pinyin unable to find, the character
     * itself will be used.
     * <p>
     * The below additional name lookup keys will be generated.
     * a. Chinese character's pinyin and pinyin's initial character.
     * b. Latin word and the initial character for Latin word.
     * The name lookup keys are generated to make sure the name can be found by from any
     * initial character.
     */
    private class ChineseContactUtils extends ContactLocaleUtilsBase {
        @Override
        public String getSortKey(String displayName) {
            ArrayList<Token> tokens = HanziToPinyin.getInstance().get(displayName);
            if (tokens != null && tokens.size() > 0) {
                StringBuilder sb = new StringBuilder();
                for (Token token : tokens) {
                    // Put Chinese character's pinyin, then proceed with the
                    // character itself.
                    if (Token.PINYIN == token.type) {
                        if (sb.length() > 0) {
                            sb.append(' ');
                        }
                        sb.append(token.target);
                        sb.append(' ');
                        sb.append(token.source);
                    } else {
                        if (sb.length() > 0) {
                            sb.append(' ');
                        }
                        sb.append(token.source);
                    }
                }
                return sb.toString();
            }
            return super.getSortKey(displayName);
        }

        @Override
        public Iterator<String> getNameLookupKeys(String name) {
            // TODO : Reduce the object allocation.
            HashSet<String> keys = new HashSet<String>();
            ArrayList<Token> tokens = HanziToPinyin.getInstance().get(name);
            final int tokenCount = tokens.size();
            final StringBuilder keyPinyin = new StringBuilder();
            final StringBuilder keyInitial = new StringBuilder();
            // There is no space among the Chinese Characters, the variant name
            // lookup key wouldn't work for Chinese. The keyOrignal is used to
            // build the lookup keys for itself.
            final StringBuilder keyOrignal = new StringBuilder();
            for (int i = tokenCount - 1; i >= 0; i--) {
                final Token token = tokens.get(i);
                if (Token.PINYIN == token.type) {
                    keyPinyin.insert(0, token.target);
                    keyInitial.insert(0, token.target.charAt(0));
                } else if (Token.LATIN == token.type) {
                    // Avoid adding space at the end of String.
                    if (keyPinyin.length() > 0) {
                        keyPinyin.insert(0, ' ');
                    }
                    if (keyOrignal.length() > 0) {
                        keyOrignal.insert(0, ' ');
                    }
                    keyPinyin.insert(0, token.source);
                    keyInitial.insert(0, token.source.charAt(0));
                }
                keyOrignal.insert(0, token.source);
                keys.add(keyOrignal.toString());
                keys.add(keyPinyin.toString());
                keys.add(keyInitial.toString());
            }
            return keys.iterator();
        }
    }

    private static final String CHINESE_LANGUAGE = Locale.CHINESE.getLanguage().toLowerCase();
    private static final String JAPANESE_LANGUAGE = Locale.JAPANESE.getLanguage().toLowerCase();
    private static final String KOREAN_LANGUAGE = Locale.KOREAN.getLanguage().toLowerCase();

    private static ContactLocaleUtils sSingleton;
    private final SparseArray<ContactLocaleUtilsBase> mUtils =
            new SparseArray<ContactLocaleUtilsBase>();

    private final ContactLocaleUtilsBase mBase = new ContactLocaleUtilsBase();

    private String mLanguage;

    private ContactLocaleUtils() {
        setLocale(null);
    }

    public void setLocale(Locale currentLocale) {
        if (currentLocale == null) {
            mLanguage = Locale.getDefault().getLanguage().toLowerCase();
        } else {
            mLanguage = currentLocale.getLanguage().toLowerCase();
        }
    }

    public String getSortKey(String displayName, int nameStyle) {
        return getForSort(Integer.valueOf(nameStyle)).getSortKey(displayName);
    }
    
    public String getPinYin(String input) {  
        ArrayList<Token> tokens = HanziToPinyin.getInstance().get(input);  
        StringBuilder sb = new StringBuilder();  
        if (tokens != null && tokens.size() > 0) {  
            for (Token token : tokens) {  
                if (Token.PINYIN == token.type) {  
                    sb.append(token.target);  
                } else {  
                    sb.append(token.source);  
                }  
            }  
        }  
        return sb.toString().toLowerCase();  
    } 
    
    
    public String getFirstPinYin(String source){  
    	if (!Arrays.asList(Collator.getAvailableLocales()).contains(Locale.CHINA)) {   
    		return source;  
    	}   
        ArrayList<Token> tokens = HanziToPinyin.getInstance().get(source);  
        if (tokens == null || tokens.size() == 0) {  
           return source;   
        }   
        StringBuffer result = new StringBuffer();  
     
        for (Token token : tokens) {  
        	if (token.type == Token.PINYIN) {  
        		result.append(token.target.charAt(0));  
     
        	} 
        	else {  
        		result.append("#"); 
        	}   
          
        }
        
        String ret = result.toString();
        return ret.toLowerCase();
    }    
    
    

    public Iterator<String> getNameLookupKeys(String name, int nameStyle) {
        return getForNameLookup(Integer.valueOf(nameStyle)).getNameLookupKeys(name);
    }

    /**
     *  Determine which utility should be used for generating NameLookupKey.
     *  <p>
     *  a. For Western style name, if the current language is Chinese, the
     *     ChineseContactUtils should be used.
     *  b. For Chinese and CJK style name if current language is neither Japanese or Korean,
     *     the ChineseContactUtils should be used.
     */
    private ContactLocaleUtilsBase getForNameLookup(Integer nameStyle) {
        int nameStyleInt = nameStyle.intValue();
        Integer adjustedUtil = Integer.valueOf(getAdjustedStyle(nameStyleInt));
        if (CHINESE_LANGUAGE.equals(mLanguage) && nameStyleInt == FullNameStyle.WESTERN) {
            adjustedUtil = Integer.valueOf(FullNameStyle.CHINESE);
        }
        return get(adjustedUtil);
    }

    private synchronized ContactLocaleUtilsBase get(Integer nameStyle) {
        ContactLocaleUtilsBase utils = mUtils.get(nameStyle);
        if (utils == null) {
            if (nameStyle.intValue() == FullNameStyle.CHINESE) {
                utils = new ChineseContactUtils();
                mUtils.put(nameStyle, utils);
            }
        }
        return (utils == null) ? mBase : utils;
    }

    /**
     *  Determine the which utility should be used for generating sort key.
     *  <p>
     *  For Chinese and CJK style name if current language is neither Japanese or Korean,
     *  the ChineseContactUtils should be used.
     */
    private ContactLocaleUtilsBase getForSort(Integer nameStyle) {
        return get(Integer.valueOf(getAdjustedStyle(nameStyle.intValue())));
    }

    public static synchronized ContactLocaleUtils getIntance() {
        if (sSingleton == null) {
            sSingleton = new ContactLocaleUtils();
        }
        return sSingleton;
    }

    private int getAdjustedStyle(int nameStyle) {
        if (nameStyle == FullNameStyle.CJK  && !JAPANESE_LANGUAGE.equals(mLanguage) &&
                !KOREAN_LANGUAGE.equals(mLanguage)) {
            return FullNameStyle.CHINESE;
        } else {
            return nameStyle;
        }
    }
}




package com.example.sharingcontact.db;

import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteStatement;

/* 数据库的组织方法
 * local表----本地联系人信息表
 * del表------删除表(未同步)
 * ins表------新添表(未同步)
 * upd表------更新表(未同步)
 * remote表---服务器下的同步表名
 * */
public class Contacts {
	private DatabaseOperation dbOp = null;	
	private String dbName = "Contacts124.db";
	private int Version = 1;
	private String mainTable = "local";	
	private String deleteTable = "del";
	private String insertTable = "ins";
	private String updateTable = "upd";
	private String remoteTable = "remote";
	
	/* 功能:新建通讯录
	 * */	
	public Contacts(Context activityContext){		
		dbOp = new DatabaseOperation(activityContext);
		dbOp.readWDb(dbName, Version);	
		
		createMainTable();
		createInsertTable();
		createDeleteTable();
		createUpdateTable();
		createRemoteTable();
	}
	/* 功能:关闭联系人操作
	 * */
	public void closeContacts(){
		dbOp.closeDb();
	}
	/* 功能:读取所有联系人信息
	 * */
	public ContactInfo[] readContacts(){
		String sqlQuery = "";
		ContactInfo[] infos = null;
		int nRecordCnt = 0;
		int index = 0;
		
		sqlQuery = "SELECT * FROM " +"'"+mainTable+"'"+" ORDER BY Sort_Key ASC"+";";		
		Cursor result = dbOp.queryDb(sqlQuery);
		nRecordCnt = result.getCount();
		
		if(nRecordCnt>0)
		{
			infos = new ContactInfo[nRecordCnt];
			for(int j=0; j<nRecordCnt; j++)
				infos[j] = new ContactInfo();
			
			index = 0;
			result.moveToFirst();			
			while(!result.isAfterLast()){
				infos[index].ContactID = result.getInt(0);
				infos[index].Name = result.getString(1);			
				infos[index].SubName = result.getString(2);
				infos[index].MobileTel = result.getString(3);
				infos[index].FixedTel = result.getString(4);
				infos[index].Company = result.getString(5);
				infos[index].Address = result.getString(6);	
				infos[index].ImageId = result.getInt(7);
				index++;
				result.moveToNext();
			}
			result.close();
		}
		
		return infos;		
	}
	/* 功能:添加一条记录
	 * p:添加人信息
	 * */
	public void insertContacts(ContactInfo info){
		insertMainTable(info);
		insertInsertTable(info);
	}
	/* 导入sim卡
	 * */
	public void readLocalContacts(ContactInfo[] infos){
		if(infos == null)
		{
			return;
		}
		
		int firstID, lastID, simLen;
		
		batInsertWithoutID(mainTable, infos);	
		
		String sqlQuery = "SELECT * FROM '"+mainTable+"';";
		Cursor result= dbOp.queryDb(sqlQuery);
		result.moveToLast();
		lastID = (int) result.getLong(0);
		
		simLen = infos.length;
		firstID = lastID - simLen;
		for(int i=0; i<infos.length; i++){
			infos[i].ContactID = firstID + i +1;
		}
		
		batInsertWithID(insertTable, infos);
	}	
	
	/* 功能:删除一条记录
	 * Id:删除人ID号
	 * */ 
	public void deleteContacts(int Id){
		deleteTable(mainTable, Id);
		insertDeleteTable(Id);
	}
	/* 功能:批量删除联系人
	 * */
	public void batDeleteContacts(int[] Ids){
		int Num = Ids.length;
		ContactInfo[] infos = new ContactInfo[Num];
		for(int i=0; i<Num; i++)
		{
			infos[i] = new ContactInfo();
			infos[i].ContactID = Ids[i];
		}
		
		batDeleteContacts(mainTable, infos);
		batSaveDeleteContacts(deleteTable, infos);
	}
	/* 功能:删除所有联系人
	 * */
	public void clearContacts(){
		ContactInfo[] infos = traverseContacts(mainTable);
		
		batSaveDeleteContacts(deleteTable, infos);
		deletaAllContacts();
	}
	/* 功能:修改联系人信息
	 * p:修改后的联系人信息
	 * */
	public void updateContacts(ContactInfo info){
		UpdateMainTable(info);
		insertUpdateTable(info);		
	}	
	/* 功能:查询记录
	 * keyValue:查询人名字或电话
	 * */
	public ContactInfo[] queryContacts(String keyValue){
		String sqlQuery = "";
		ContactInfo[] infos = null;
		int nRecordCnt = 0;
		int index = 0;
		
		sqlQuery = "SELECT * FROM " +
				"'"+mainTable+"'" +	
				" WHERE "+
				"MobileTel LIKE '%"+keyValue+"%'"+
				" OR " +
				"Name LIKE '%"+keyValue+"%'" +
				" OR " +				
				"Pinyin_Key LIKE '%"+keyValue.toLowerCase()+"%'" +
				" OR " +				
				"FPinyin_Key LIKE '%"+keyValue.toLowerCase()+"%'" +				
				" ORDER BY Sort_Key ASC"+
				";";		
		Cursor result = dbOp.queryDb(sqlQuery);
		nRecordCnt = result.getCount();
		
		if(nRecordCnt>0)
		{
			infos = new ContactInfo[nRecordCnt];
			for(int j=0; j<nRecordCnt; j++)
				infos[j] = new ContactInfo();
			
			index = 0;
			result.moveToFirst();			
			while(!result.isAfterLast()){
				infos[index].ContactID = result.getInt(0);
				infos[index].Name = result.getString(1);			
				infos[index].SubName = result.getString(2);
				infos[index].MobileTel = result.getString(3);
				infos[index].FixedTel = result.getString(4);
				infos[index].Company = result.getString(5);
				infos[index].Address = result.getString(6);	
				infos[index].ImageId = result.getInt(7);
				index++;
				result.moveToNext();
			}
			result.close();
		}
		
		return infos;
	}
	/* 功能:导入联系人
	 * */
	public void importContacts(ContactInfo[] infos){
		clearTable(mainTable);
		clearTable(insertTable);
		clearTable(updateTable);
		clearTable(deleteTable);
		
		batInsertWithID(mainTable, infos);
	}
	/* 同步的前端操作,获取数据
	 * */
	public ContactInfo[][] syncContactsPre(){
		ContactInfo[][] infoss = syncContactsToServer();
		
		return infoss;
	}
	/* 同步成功的后续操作
	 * */
	public void syncContactsPost(){	
		clearTable(insertTable);
		clearTable(updateTable);
		clearTable(deleteTable);
	}	
	
	public String readInfoInServer(){
		String result = queryRemoteTable();
		
		return result;
	}
	
	public void writeInfoInServer(String utl){
		String result = queryRemoteTable();
		if(result == null){
			insertRemoteTable(utl);
		}
		else{
			updateRemoteTable(utl);
		}
	}
	
	
	private void batInsertWithID(String tableName, ContactInfo[] infos){
		BatInsertWithID cbi = new BatInsertWithID();
		
		dbOp.batchInsertDb(tableName, cbi, infos);
	}
	
	private void batInsertWithoutID(String tableName, ContactInfo[] infos){
		BatInsertWithoutID cbi = new BatInsertWithoutID();
		
		dbOp.batchInsertDb(tableName, cbi, infos);
	}	
	
	
	/* 功能:批量保存被删联系人
	 * */
	private void batSaveDeleteContacts(String tableName, ContactInfo[] infos){
		contactsBatSaveDelete cbi = new contactsBatSaveDelete();
		
		dbOp.batchInsertDb(tableName, cbi, infos);
	}
	/* 功能:批量删除联系人
	 * */
	private void batDeleteContacts(String tableName, ContactInfo[] infos){
		contactsBatDelete cbd = new contactsBatDelete();
		
		dbOp.batchDeleteDb(tableName, cbd, infos);
	}		
	/* 功能:获取本地变动的联系人信息
	 * */
	private ContactInfo[][] syncContactsToServer(){		
		
		ContactInfo[] infosInsert = traverseContacts(insertTable);
		ContactInfo[] infosUpdata = traverseContacts(updateTable);
		ContactInfo[] infosDelete = traverseContacts(deleteTable);
		
		ContactInfo[][] infoss= new ContactInfo[3][];
		infoss[0] = infosInsert;
		infoss[1] = infosUpdata;
		infoss[2] = infosDelete;		
				
		return infoss;
	}	
	
	/* 功能:遍历表
	 * */
	private ContactInfo[] traverseContacts(String tableName){
		String sqlQuery = "";
		ContactInfo[] infos = null;
		int nRecordCnt = 0;
		int index = 0;
		
		sqlQuery = "SELECT * FROM '"+tableName+"';";		
		Cursor result = dbOp.queryDb(sqlQuery);
		nRecordCnt = result.getCount();
		
		if(nRecordCnt>0)
		{
			infos = new ContactInfo[nRecordCnt];
			for(int j=0; j<nRecordCnt; j++)
				infos[j] = new ContactInfo();
			
			index = 0;
			result.moveToFirst();			
			while(!result.isAfterLast()){
				if(tableName == mainTable)
				{
					infos[index].ContactID = result.getInt(0);
				}
				else if(tableName == deleteTable)
				{
					infos[index].ContactID = result.getInt(1);
				}
				else{
					infos[index].ContactID = result.getInt(1);
					infos[index].Name = result.getString(2);			
					infos[index].SubName = result.getString(3);
					infos[index].MobileTel = result.getString(4);
					infos[index].FixedTel = result.getString(5);
					infos[index].Company = result.getString(6);
					infos[index].Address = result.getString(7);	
					infos[index].ImageId = result.getInt(8);					
				}
				index++;
				result.moveToNext();
			}
			result.close();
		}
		
		return infos;
	}	
	
	/* MainTable
	 * */
	private void createMainTable(){
		String sqlCreate = "CREATE TABLE IF NOT EXISTS " +
				"'"+mainTable+"' " +
				"(" +
				"ContactID INTEGER PRIMARY KEY AUTOINCREMENT"+"," +
				"Name TEXT" 		+"," 	+
				"SubName TEXT" 		+"," 	+
				"MobileTel TEXT"	+"," 	+
				"FixedTel TEXT"		+"," 	+
				"Company TEXT"		+"," 	+
				"Address TEXT"		+"," 	+
				"ImageId INTEGER" 	+"," 	+
				"Sort_Key TEXT"		+"," 	+
				"Pinyin_Key TEXT"	+","	+
				"FPinyin_Key TEXT"	+
				")" 				+
				";";		
		dbOp.createDbTab(sqlCreate);
	}	
	private void insertMainTable(ContactInfo info){		
		String sqlInsert = "INSERT INTO " +
				"'"+mainTable+"' " +
				"(Name, SubName, MobileTel, FixedTel, Company, Address, ImageId, Sort_Key, Pinyin_Key, FPinyin_Key)"+
				" VALUES "+"(" +
				"'"+info.Name+"'"					+"," +
				"'"+info.SubName+"'"				+"," +
				"'"+info.MobileTel+"'"				+"," +
				"'"+info.FixedTel+"'"				+"," +
				"'"+info.Company+"'"				+"," +
				"'"+info.Address+"'"				+"," +
				String.valueOf(info.ImageId)		+"," +
				"'"+info.getSortKey(info)+"'"		+"," +
				"'"+info.getPinyin(info)+"'"		+"," +
				"'"+info.getFisrtPinyin(info)+"'"	+
				");";			
		
		dbOp.insertDb(sqlInsert);		
	}
	private void UpdateMainTable(ContactInfo info){
		if(info == null)
			return;
		
		String sqlUpdate = "UPDATE " +
				"'"+mainTable+"'" +" SET "+ 
				"Name=" 		+"'"+info.Name+"'" 					+"," +
				"SubName=" 		+"'"+info.SubName+"'" 				+"," +
				"MobileTel=" 	+"'"+info.MobileTel+"'" 			+"," +
				"FixedTel=" 	+"'"+info.FixedTel+"'" 				+"," +
				"Company=" 		+"'"+info.Company+"'" 				+"," +
				"Address=" 		+"'"+info.Address+"'" 				+"," +
				"ImageId="		+String.valueOf(info.ImageId)		+"," +
				"Sort_Key="		+"'"+info.getSortKey(info)+"'"		+"," +
				"Pinyin_Key="	+"'"+info.getPinyin(info)+"'"		+"," +
				"FPinyin_Key="	+"'"+info.getFisrtPinyin(info)+"'"	+
				" WHERE ContactID="+String.valueOf(info.ContactID)+
				";";		
		dbOp.updataDb(sqlUpdate);	
	}	
	/* insertTable
	 * */
	private void createInsertTable(){
		String sqlCreate = "CREATE TABLE IF NOT EXISTS " +
				"'"+insertTable+"' " +
				"(" +
				"ID INTEGER PRIMARY KEY AUTOINCREMENT" 	+"," +
				"ContactID INTEGER" 					+"," +
				"Name TEXT" 							+"," +
				"SubName TEXT"						 	+"," +
				"MobileTel TEXT" 						+"," +
				"FixedTel TEXT" 						+"," +
				"Company TEXT" 							+"," +
				"Address TEXT" 							+"," +
				"ImageId INTEGER" 						+"," +
				"Sort_Key TEXT"							+"," +
				"Pinyin_Key TEXT"						+"," +
				"FPinyin_Key TEXT"						+
				");";
		dbOp.createDbTab(sqlCreate);			
	}	
	private void insertInsertTable(ContactInfo info){
		if(info == null)
			return;		
		
		String sqlQuery = "SELECT * FROM '"+mainTable+"';";
		Cursor result= dbOp.queryDb(sqlQuery);
		result.moveToLast();
		info.ContactID = (int) result.getLong(0);
		
		String sqlInsert = "INSERT INTO " +
				"'"+insertTable+"' " +
				"(ContactID, Name, SubName, MobileTel, FixedTel, Company, Address, ImageId, Sort_Key, Pinyin_Key, FPinyin_Key)"+
				" VALUES "+"("+
				String.valueOf(info.ContactID)		+"," +
				"'"+info.Name+"'" 					+"," +
				"'"+info.SubName+"'" 				+"," +
				"'"+info.MobileTel+"'" 				+"," +
				"'"+info.FixedTel+"'" 				+"," +
				"'"+info.Company+"'" 				+"," +
				"'"+info.Address+"'" 				+"," +
				String.valueOf(info.ImageId)		+"," +
				"'"+info.getSortKey(info)+"'"		+"," +
				"'"+info.getPinyin(info)+"'"		+"," +
				"'"+info.getFisrtPinyin(info)+"'"	+
				");";		
		dbOp.insertDb(sqlInsert);			
	}
	/* updateTable
	 * */	
	private void createUpdateTable(){
		String sqlCreate = "CREATE TABLE IF NOT EXISTS " +
				"'"+updateTable+"' " +
				"("+
				"ID INTEGER PRIMARY KEY AUTOINCREMENT" 	+"," +
				"ContactID INTEGER" 					+"," +
				"Name TEXT" 							+"," +
				"SubName TEXT" 							+"," +
				"MobileTel TEXT" 						+"," +
				"FixedTel TEXT" 						+"," +
				"Company TEXT" 							+"," +
				"Address TEXT" 							+"," +
				"ImageId INTEGER" 						+"," +
				"Sort_Key TEXT"							+"," + 
				"Pinyin_Key TEXT"						+"," +
				"FPinyin_Key TEXT"						+
				");";
		dbOp.createDbTab(sqlCreate);			
	}	
	private void insertUpdateTable(ContactInfo info){
		if(info == null)
			return;		
		
		String sqlInsert = "INSERT INTO " +
				"'"+updateTable+"' " +
				"(ContactID, Name, SubName, MobileTel, FixedTel, Company, Address, ImageId, Sort_Key, Pinyin_Key, FPinyin_Key)"+
				" VALUES "+"("+
				String.valueOf(info.ContactID)		+","  +
				"'"+info.Name+"'" 					+","  +
				"'"+info.SubName+"'" 				+","  +
				"'"+info.MobileTel+"'" 				+"," +
				"'"+info.FixedTel+"'"				+","  +
				"'"+info.Company+"'" 				+","  +
				"'"+info.Address+"'" 				+","  +
				String.valueOf(info.ImageId)  		+","  +
				"'"+info.getSortKey(info)+"'" 		+","  +
				"'"+info.getPinyin(info)+"'" 		+","  +
				"'"+info.getFisrtPinyin(info)+"'" 	+
				");";		
		dbOp.insertDb(sqlInsert);	 	
	}
	/* deleteTable
	 * */
	private void createDeleteTable(){
		String sqlCreate = "CREATE TABLE IF NOT EXISTS " +
				"'"+deleteTable+"' " +
				"(" +
				"ID INTEGER PRIMARY KEY AUTOINCREMENT," +
				"ContactID INTEGER"		+
				");";
		dbOp.createDbTab(sqlCreate);		
	}	
	private void insertDeleteTable(int Id){
		String sqlInsert = "INSERT INTO " +
				"'"+deleteTable+"' " +
				"(ContactID)"+
				" VALUES "+"("+
				String.valueOf(Id)+
				")";	
		dbOp.insertDb(sqlInsert);	
	}
	/* remoteTable
	 * */
	private void createRemoteTable(){
		String sqlCreate = "CREATE TABLE IF NOT EXISTS '"+remoteTable+
				"' (ID INTEGER PRIMARY KEY AUTOINCREMENT, utl TEXT);";
		dbOp.createDbTab(sqlCreate);
	}
	
	private void insertRemoteTable(String utl){		
		String sqlInsert = "INSERT INTO " +
				"'"+remoteTable+"' " +
				"(utl)"+
				" VALUES "+"(" +
				"'"+utl+"'" +
				")";
		
		dbOp.insertDb(sqlInsert);
	}
	private void updateRemoteTable(String utl){
		String sqlUpdate = "UPDATE "	+
				"'"+remoteTable+"'"+" SET "	+
				"utl="+"'"+utl+"'"+				
				";"
				;
		
		dbOp.updataDb(sqlUpdate);
	}
	private String queryRemoteTable(){
		String sqlQuery = "SELECT * FROM " +"'"+remoteTable+"'" +";";
		Cursor result = dbOp.queryDb(sqlQuery);
		if(result.getCount() == 0)
			return null;
		else{
			result.moveToFirst();
			return result.getString(1);
		}
	}
	
	

	/* delete table record
	 * */
	private void deleteTable(String tableName, int Id){
		String key = "ContactID";
		String sqlDelete = "DELETE FROM " +
				"'"+tableName+"' " +
				"WHERE "+key+"="+String.valueOf(Id)+";";		
		dbOp.deleteDb(sqlDelete);	
	}	
	/* clear table
	 * */
	private void clearTable(String tableName){
		String sqlDelete = "DELETE FROM " +"'"+tableName+"'" +";";
		dbOp.deleteDb(sqlDelete);
		
		String sqlUpdate = "UPDATE sqlite_sequence SET seq = 0 WHERE name= '"+tableName+"';";
		dbOp.deleteDb(sqlUpdate);
	}
	/* 功能:联系人清零
	 * */
	private void deletaAllContacts(){
		String sqlDelete = "DELETE FROM " +"'"+mainTable+"'" +";";
		dbOp.deleteDb(sqlDelete);		
	}
}



/* 批量插入联系人,含ID
 * */
class BatInsertWithID implements DbBatInsert{
	public void batInsert(String tableName, SQLiteDatabase db, ContactInfo[] infos){
		if(infos == null)
			return;
		
		for(int i=0; i<infos.length; i++)
		{	
			String sqlInsert = "INSERT INTO"+
					" '"+tableName+"' "+
					"(ContactID, Name, SubName, MobileTel, FixedTel, Company, Address, ImageId, Sort_Key, Pinyin_Key, FPinyin_Key)"+
					" VALUES "+"("+
					String.valueOf(infos[i].ContactID)			+","  +
					"'"+infos[i].Name+"'" 						+","  +
					"'"+infos[i].SubName+"'" 					+","  +
					"'"+infos[i].MobileTel+"'" 					+"," +
					"'"+infos[i].FixedTel+"'"					+","  +
					"'"+infos[i].Company+"'" 					+","  +
					"'"+infos[i].Address+"'" 					+","  +
					String.valueOf(infos[i].ImageId)  			+","  +
					"'"+infos[i].getSortKey(infos[i])+"'" 		+","  +
					"'"+infos[i].getPinyin(infos[i])+"'" 		+","  +
					"'"+infos[i].getFisrtPinyin(infos[i])+"'" 	+
					");";	
			db.execSQL(sqlInsert);
		}
	}	
}


/* 批量插入联系人, 无ID
 * */
class BatInsertWithoutID implements DbBatInsert{
	public void batInsert(String tableName, SQLiteDatabase db, ContactInfo[] infos){
		if(infos == null)
			return;
		
		for(int i=0; i<infos.length; i++)
		{	
			String sqlInsert = "INSERT INTO"+
					" '"+tableName+"' "+
					"(Name, SubName, MobileTel, FixedTel, Company, Address, ImageId, Sort_Key, Pinyin_Key, FPinyin_Key)"+
					" VALUES "+"("+
					"'"+infos[i].Name+"'" 						+","  +
					"'"+infos[i].SubName+"'" 					+","  +
					"'"+infos[i].MobileTel+"'" 					+"," +
					"'"+infos[i].FixedTel+"'"					+","  +
					"'"+infos[i].Company+"'" 					+","  +
					"'"+infos[i].Address+"'" 					+","  +
					String.valueOf(infos[i].ImageId)  			+","  +
					"'"+infos[i].getSortKey(infos[i])+"'" 		+","  +
					"'"+infos[i].getPinyin(infos[i])+"'" 		+","  +
					"'"+infos[i].getFisrtPinyin(infos[i])+"'" 	+
					");";	
			db.execSQL(sqlInsert);
		}
	}	
}

/* 批量保存删除联系人
 * */
class contactsBatSaveDelete implements DbBatInsert{
	public void batInsert(String tableName, SQLiteDatabase db, ContactInfo[] infos){
		if(infos == null)
			return;
		
		for(int i=0; i<infos.length; i++)
		{	
			String sqlInsert = "INSERT INTO"+
					" '"+tableName+"' "+
					"(ContactID)"+
					" VALUES "+"("+
					String.valueOf(infos[i].ContactID)	+
					");";	
			db.execSQL(sqlInsert);
		}
	}		
}
/* 批量更新
 * */
class contactsBatUpdate implements DbBatUpdate{
	public void batUpdate(String tableName, SQLiteDatabase db, ContactInfo[] infos){
		if(infos == null)
			return;
		
		for(int i=0; i<infos.length; i++)
		{
			String sqlUpdate ="UPDATE " +
					"'"+tableName+"' " +"SET "+ 
					"Name=" +		"'"+infos[i].Name+"'" 			+"," +
					"SubName=" +	"'"+infos[i].SubName+"'"		+"," +
					"MobileTel=" +	"'"+infos[i].MobileTel+"'" 		+"," +
					"FixedTel=" +	"'"+infos[i].FixedTel+"'" 		+"," +
					"Company=" +	"'"+infos[i].Company+"'" 		+"," +
					"Address=" +	"'"+infos[i].Address+"'" 		+"," +
					"ImageId="+String.valueOf(infos[i].ImageId)		+
					" WHERE " +
					"ContactID ="+String.valueOf(infos[i].ContactID)+
					";";	
			db.execSQL(sqlUpdate);
		}
	}	
}
/* 批量删除
 * */
class contactsBatDelete implements DbBatDelete{
	public void batDelete(String tableName, SQLiteDatabase db, ContactInfo[] infos){
		if(infos == null)
			return;		
		
		for(int i=0; i<infos.length; i++)
		{
			String key = "ContactID";
			String sqlDelete ="DELETE FROM '"+tableName+"' WHERE "+key+"="+String.valueOf(infos[i].ContactID)+";";
			db.execSQL(sqlDelete);
		}		
	}	
}





package com.example.sharingcontact.db;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;


/* 1. SQL对大小写不敏感
 * */
class DatabaseHelper extends SQLiteOpenHelper{
	
	public DatabaseHelper(Context context, String Name, int Version){
		super(context, Name, null, Version);
	}
	
	// 创建数据库时被调用
	public void onCreate(SQLiteDatabase db){
//		db.execSQL(sqlCreate);
	}	
	
	// 升级数据库时被调用
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){
//		String sql = "DROP TABLE if exits local";		
//		db.execSQL(sql);
//		onCreate(db);
	}	
}



package com.example.sharingcontact.db;

import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteStatement;
import com.example.sharingcontact.db.DatabaseHelper;

public class DatabaseOperation {
	
	private SQLiteDatabase db;
	private DatabaseHelper dbHelper;
	private Context context = null;
	
	public DatabaseOperation(Context activityContext){
		context = activityContext;
	}	
	/* 功能:创建数据库
	 * context----Activity this
	 * dbName-----数据库名
	 * Version----版本号1,2,3...
	 * sqlCreate--创建数据库表sql命令
	 * */
	public void readWDb(String dbName, int Version){
		dbHelper = new DatabaseHelper(context, dbName, Version);	
				
		db = dbHelper.getWritableDatabase();		
	}
	/* 功能:新建表
	 * 
	 * */
	public void createDbTab(String sql){
		db.execSQL(sql);
	}
	
	/* 功能:关闭数据
	 */
	public void closeDb(){
		db.close();
	}
	/* 功能:添加一条记录
	 * */
	public void insertDb(String sql){
		db.execSQL(sql);
	}
	/* 功能:更新记录
	 * sql = "UPDATE table_name SET <des_operation> WHERE <condition>"
	 * */
	public void updataDb(String Sql){
		db.execSQL(Sql);
	}	
	/* 功能:删除记录
	 * sql = "DELETE FROM table_name WHERE <condition>;"
	 * */
	public void deleteDb(String Sql){
		db.execSQL(Sql);
	}	
	/* 功能:批量插入
	 * */
	public void batchInsertDb(String tableName, DbBatInsert bi, ContactInfo[] infos){		
		db.beginTransaction();
		// 插入操作
		bi.batInsert(tableName, db, infos);
		
		db.setTransactionSuccessful();
		db.endTransaction();		
	}
	public void batchUpdateDb(String tableName, DbBatUpdate bu, ContactInfo[] infos){	
		db.beginTransaction();
		// 更新操作
		bu.batUpdate(tableName, db, infos);
		
		db.setTransactionSuccessful();
		db.endTransaction();		
	}
	public void batchDeleteDb(String tableName, DbBatDelete bd, ContactInfo[] infos){	
		db.beginTransaction();
		// 删除操作
		bd.batDelete(tableName, db, infos);
		
		db.setTransactionSuccessful();
		db.endTransaction();		
	}
	
	/* 功能:查询记录
	 * sql = "SELECT <Fields> from table_name ORDER BY <Field>"
	 * */
	public Cursor queryDb(String Sql){
		return db.rawQuery(Sql, null);
	}		
		
}

interface DbBatInsert{
	public void batInsert(String tableName, SQLiteDatabase db, ContactInfo[] infos);	
}

interface DbBatUpdate{
	public void batUpdate(String tableName, SQLiteDatabase db, ContactInfo[] infos);
}

interface DbBatDelete{
	public void batDelete(String tableName, SQLiteDatabase db, ContactInfo[] infos);
}





/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.example.sharingcontact.db;

import android.text.TextUtils;
import android.util.Log;

import java.text.Collator;
import java.util.ArrayList;
import java.util.Locale;

/**
 * An object to convert Chinese character to its corresponding pinyin string. For characters with
 * multiple possible pinyin string, only one is selected according to collator. Polyphone is not
 * supported in this implementation. This class is implemented to achieve the best runtime
 * performance and minimum runtime resources with tolerable sacrifice of accuracy. This
 * implementation highly depends on zh_CN ICU collation data and must be always synchronized with
 * ICU.
 *
 * Currently this file is aligned to zh.txt in ICU 4.6
 */
public class HanziToPinyin {
    private static final String TAG = "HanziToPinyin";

    // Turn on this flag when we want to check internal data structure.
    private static final boolean DEBUG = false;

    /**
     * Unihans array. Each unihans is the first one within same pinyin. Use it to determine pinyin
     * for all ~20k unihans.
     */
    public static final char[] UNIHANS = {
            '\u5475', '\u54ce', '\u5b89', '\u80ae', '\u51f9',
            '\u516b', '\u6300', '\u6273', '\u90a6', '\u5305', '\u5351', '\u5954', '\u4f3b',
            '\u5c44', '\u8fb9', '\u6807', '\u618b', '\u90a0', '\u69df', '\u7676', '\u5cec',
            '\u5693', '\u5a47', '\u98e1', '\u4ed3', '\u64cd', '\u518a', '\u5d7e', '\u564c',
            '\u53c9', '\u9497', '\u8fbf', '\u4f25', '\u6284', '\u8f66', '\u62bb', '\u67fd',
            '\u5403', '\u5145', '\u62bd', '\u51fa', '\u6b3b', '\u63e3', '\u5ddd', '\u75ae',
            '\u5439', '\u6776', '\u9034', '\u75b5', '\u5306', '\u51d1', '\u7c97', '\u6c46',
            '\u5d14', '\u90a8', '\u6413', '\u5491', '\u5927', '\u75b8', '\u5f53', '\u5200',
            '\u6dc2', '\u5f97', '\u6265', '\u706f', '\u6c10', '\u55f2', '\u7538', '\u5201',
            '\u7239', '\u4ec3', '\u4e1f', '\u4e1c', '\u5517', '\u561f', '\u5073', '\u5806',
            '\u9413', '\u591a', '\u5a40', '\u8bf6', '\u5940', '\u97a5', '\u800c', '\u53d1',
            '\u5e06', '\u65b9', '\u98de', '\u5206', '\u4e30', '\u8985', '\u4ecf', '\u7d11',
            '\u4f15', '\u65ee', '\u8be5', '\u7518', '\u5188', '\u768b', '\u6208', '\u7d66',
            '\u6839', '\u5e9a', '\u5de5', '\u52fe', '\u4f30', '\u74dc', '\u7f6b', '\u5173',
            '\u5149', '\u5f52', '\u886e', '\u5459', '\u54c8', '\u54b3', '\u9878', '\u82c0',
            '\u84bf', '\u8bc3', '\u9ed2', '\u62eb', '\u4ea8', '\u5677', '\u543d', '\u9f41',
            '\u5322', '\u82b1', '\u6000', '\u72bf', '\u5ddf', '\u7070', '\u660f', '\u5419',
            '\u4e0c', '\u52a0', '\u620b', '\u6c5f', '\u827d', '\u9636', '\u5dfe', '\u52a4',
            '\u5182', '\u52fc', '\u530a', '\u5a1f', '\u5658', '\u519b', '\u5494', '\u5f00',
            '\u520a', '\u95f6', '\u5c3b', '\u533c', '\u524b', '\u80af', '\u962c', '\u7a7a',
            '\u62a0', '\u5233', '\u5938', '\u84af', '\u5bbd', '\u5321', '\u4e8f', '\u5764',
            '\u6269', '\u5783', '\u6765', '\u5170', '\u5577', '\u635e', '\u4ec2', '\u52d2',
            '\u5844', '\u5215', '\u5006', '\u5941', '\u826f', '\u64a9', '\u5217', '\u62ce',
            '\u3007', '\u6e9c', '\u9f99', '\u779c', '\u565c', '\u5a08', '\u7567', '\u62a1',
            '\u7f57', '\u5463', '\u5988', '\u973e', '\u5ada', '\u9099', '\u732b', '\u9ebc',
            '\u6c92', '\u95e8', '\u753f', '\u54aa', '\u7720', '\u55b5', '\u54a9', '\u6c11',
            '\u540d', '\u8c2c', '\u6478', '\u54de', '\u6bea', '\u62cf', '\u5b7b', '\u56e1',
            '\u56ca', '\u5b6c', '\u8bb7', '\u9981', '\u6041', '\u80fd', '\u59ae', '\u62c8',
            '\u5b22', '\u9e1f', '\u634f', '\u60a8', '\u5b81', '\u599e', '\u519c', '\u7fba',
            '\u5974', '\u597b', '\u8650', '\u632a', '\u5594', '\u8bb4', '\u8db4', '\u62cd',
            '\u7705', '\u4e53', '\u629b', '\u5478', '\u55b7', '\u5309', '\u4e15', '\u504f',
            '\u527d', '\u6c15', '\u59d8', '\u4e52', '\u948b', '\u5256', '\u4ec6', '\u4e03',
            '\u6390', '\u5343', '\u545b', '\u6084', '\u767f', '\u4fb5', '\u9751', '\u909b',
            '\u4e18', '\u66f2', '\u5f2e', '\u7f3a', '\u590b', '\u5465', '\u7a63', '\u5a06',
            '\u60f9', '\u4eba', '\u6254', '\u65e5', '\u8338', '\u53b9', '\u5982', '\u5827',
            '\u6875', '\u95f0', '\u82e5', '\u4ee8', '\u6be2', '\u4e09', '\u6852', '\u63bb',
            '\u8272', '\u68ee', '\u50e7', '\u6740', '\u7b5b', '\u5c71', '\u4f24', '\u5f30',
            '\u5962', '\u7533', '\u5347', '\u5c38', '\u53ce', '\u4e66', '\u5237', '\u6454',
            '\u95e9', '\u53cc', '\u8c01', '\u542e', '\u5981', '\u53b6', '\u5fea', '\u635c',
            '\u82cf', '\u72fb', '\u590a', '\u5b59', '\u5506', '\u4ed6', '\u82d4', '\u574d',
            '\u94f4', '\u5932', '\u5fd1', '\u71a5', '\u5254', '\u5929', '\u4f7b', '\u5e16',
            '\u5385', '\u56f2', '\u5077', '\u92c0', '\u6e4d', '\u63a8', '\u541e', '\u6258',
            '\u6316', '\u6b6a', '\u5f2f', '\u5c2a', '\u5371', '\u586d', '\u7fc1', '\u631d',
            '\u5140', '\u5915', '\u867e', '\u4eda', '\u4e61', '\u7071', '\u4e9b', '\u5fc3',
            '\u661f', '\u51f6', '\u4f11', '\u65f4', '\u8f69', '\u75b6', '\u52cb', '\u4e2b',
            '\u6079', '\u592e', '\u5e7a', '\u8036', '\u4e00', '\u6b2d', '\u5e94', '\u54df',
            '\u4f63', '\u4f18', '\u625c', '\u9e22', '\u66f0', '\u6655', '\u531d', '\u707d',
            '\u7ccc', '\u7242', '\u50ae', '\u5219', '\u8d3c', '\u600e', '\u5897', '\u5412',
            '\u635a', '\u6cbe', '\u5f20', '\u948a', '\u8707', '\u8d1e', '\u4e89', '\u4e4b',
            '\u4e2d', '\u5dde', '\u6731', '\u6293', '\u8de9', '\u4e13', '\u5986', '\u96b9',
            '\u5b92', '\u5353', '\u5b5c', '\u5b97', '\u90b9', '\u79df', '\u94bb', '\u539c',
            '\u5c0a', '\u6628', };

    /**
     * Pinyin array. Each pinyin is corresponding to unihans of same offset in the unihans array.
     */
    public static final byte[][] PINYINS = {
            { 65, 0, 0, 0, 0, 0 }, { 65, 73, 0, 0, 0, 0 }, { 65, 78, 0, 0, 0, 0 },
            { 65, 78, 71, 0, 0, 0 }, { 65, 79, 0, 0, 0, 0 }, { 66, 65, 0, 0, 0, 0 },
            { 66, 65, 73, 0, 0, 0 }, { 66, 65, 78, 0, 0, 0 }, { 66, 65, 78, 71, 0, 0 },
            { 66, 65, 79, 0, 0, 0 }, { 66, 69, 73, 0, 0, 0 }, { 66, 69, 78, 0, 0, 0 },
            { 66, 69, 78, 71, 0, 0 }, { 66, 73, 0, 0, 0, 0 }, { 66, 73, 65, 78, 0, 0 },
            { 66, 73, 65, 79, 0, 0 }, { 66, 73, 69, 0, 0, 0 }, { 66, 73, 78, 0, 0, 0 },
            { 66, 73, 78, 71, 0, 0 }, { 66, 79, 0, 0, 0, 0 }, { 66, 85, 0, 0, 0, 0 },
            { 67, 65, 0, 0, 0, 0 }, { 67, 65, 73, 0, 0, 0 },
            { 67, 65, 78, 0, 0, 0 }, { 67, 65, 78, 71, 0, 0 }, { 67, 65, 79, 0, 0, 0 },
            { 67, 69, 0, 0, 0, 0 }, { 67, 69, 78, 0, 0, 0 }, { 67, 69, 78, 71, 0, 0 },
            { 67, 72, 65, 0, 0, 0 }, { 67, 72, 65, 73, 0, 0 }, { 67, 72, 65, 78, 0, 0 },
            { 67, 72, 65, 78, 71, 0 }, { 67, 72, 65, 79, 0, 0 }, { 67, 72, 69, 0, 0, 0 },
            { 67, 72, 69, 78, 0, 0 }, { 67, 72, 69, 78, 71, 0 }, { 67, 72, 73, 0, 0, 0 },
            { 67, 72, 79, 78, 71, 0 }, { 67, 72, 79, 85, 0, 0 }, { 67, 72, 85, 0, 0, 0 },
            { 67, 72, 85, 65, 0, 0 }, { 67, 72, 85, 65, 73, 0 }, { 67, 72, 85, 65, 78, 0 },
            { 67, 72, 85, 65, 78, 71 }, { 67, 72, 85, 73, 0, 0 }, { 67, 72, 85, 78, 0, 0 },
            { 67, 72, 85, 79, 0, 0 }, { 67, 73, 0, 0, 0, 0 }, { 67, 79, 78, 71, 0, 0 },
            { 67, 79, 85, 0, 0, 0 }, { 67, 85, 0, 0, 0, 0 }, { 67, 85, 65, 78, 0, 0 },
            { 67, 85, 73, 0, 0, 0 }, { 67, 85, 78, 0, 0, 0 }, { 67, 85, 79, 0, 0, 0 },
            { 68, 65, 0, 0, 0, 0 }, { 68, 65, 73, 0, 0, 0 }, { 68, 65, 78, 0, 0, 0 },
            { 68, 65, 78, 71, 0, 0 }, { 68, 65, 79, 0, 0, 0 }, { 68, 69, 0, 0, 0, 0 },
            { 68, 69, 73, 0, 0, 0 }, { 68, 69, 78, 0, 0, 0 }, { 68, 69, 78, 71, 0, 0 },
            { 68, 73, 0, 0, 0, 0 }, { 68, 73, 65, 0, 0, 0 }, { 68, 73, 65, 78, 0, 0 },
            { 68, 73, 65, 79, 0, 0 }, { 68, 73, 69, 0, 0, 0 }, { 68, 73, 78, 71, 0, 0 },
            { 68, 73, 85, 0, 0, 0 }, { 68, 79, 78, 71, 0, 0 }, { 68, 79, 85, 0, 0, 0 },
            { 68, 85, 0, 0, 0, 0 }, { 68, 85, 65, 78, 0, 0 }, { 68, 85, 73, 0, 0, 0 },
            { 68, 85, 78, 0, 0, 0 }, { 68, 85, 79, 0, 0, 0 }, { 69, 0, 0, 0, 0, 0 },
            { 69, 73, 0, 0, 0, 0 }, { 69, 78, 0, 0, 0, 0 }, { 69, 78, 71, 0, 0, 0 },
            { 69, 82, 0, 0, 0, 0 }, { 70, 65, 0, 0, 0, 0 }, { 70, 65, 78, 0, 0, 0 },
            { 70, 65, 78, 71, 0, 0 }, { 70, 69, 73, 0, 0, 0 }, { 70, 69, 78, 0, 0, 0 },
            { 70, 69, 78, 71, 0, 0 }, { 70, 73, 65, 79, 0, 0 }, { 70, 79, 0, 0, 0, 0 },
            { 70, 79, 85, 0, 0, 0 }, { 70, 85, 0, 0, 0, 0 }, { 71, 65, 0, 0, 0, 0 },
            { 71, 65, 73, 0, 0, 0 }, { 71, 65, 78, 0, 0, 0 }, { 71, 65, 78, 71, 0, 0 },
            { 71, 65, 79, 0, 0, 0 }, { 71, 69, 0, 0, 0, 0 }, { 71, 69, 73, 0, 0, 0 },
            { 71, 69, 78, 0, 0, 0 }, { 71, 69, 78, 71, 0, 0 }, { 71, 79, 78, 71, 0, 0 },
            { 71, 79, 85, 0, 0, 0 }, { 71, 85, 0, 0, 0, 0 }, { 71, 85, 65, 0, 0, 0 },
            { 71, 85, 65, 73, 0, 0 }, { 71, 85, 65, 78, 0, 0 }, { 71, 85, 65, 78, 71, 0 },
            { 71, 85, 73, 0, 0, 0 }, { 71, 85, 78, 0, 0, 0 }, { 71, 85, 79, 0, 0, 0 },
            { 72, 65, 0, 0, 0, 0 }, { 72, 65, 73, 0, 0, 0 }, { 72, 65, 78, 0, 0, 0 },
            { 72, 65, 78, 71, 0, 0 }, { 72, 65, 79, 0, 0, 0 }, { 72, 69, 0, 0, 0, 0 },
            { 72, 69, 73, 0, 0, 0 }, { 72, 69, 78, 0, 0, 0 }, { 72, 69, 78, 71, 0, 0 },
            { 72, 77, 0, 0, 0, 0 }, { 72, 79, 78, 71, 0, 0 }, { 72, 79, 85, 0, 0, 0 },
            { 72, 85, 0, 0, 0, 0 }, { 72, 85, 65, 0, 0, 0 }, { 72, 85, 65, 73, 0, 0 },
            { 72, 85, 65, 78, 0, 0 }, { 72, 85, 65, 78, 71, 0 }, { 72, 85, 73, 0, 0, 0 },
            { 72, 85, 78, 0, 0, 0 }, { 72, 85, 79, 0, 0, 0 }, { 74, 73, 0, 0, 0, 0 },
            { 74, 73, 65, 0, 0, 0 }, { 74, 73, 65, 78, 0, 0 }, { 74, 73, 65, 78, 71, 0 },
            { 74, 73, 65, 79, 0, 0 }, { 74, 73, 69, 0, 0, 0 }, { 74, 73, 78, 0, 0, 0 },
            { 74, 73, 78, 71, 0, 0 }, { 74, 73, 79, 78, 71, 0 }, { 74, 73, 85, 0, 0, 0 },
            { 74, 85, 0, 0, 0, 0 }, { 74, 85, 65, 78, 0, 0 }, { 74, 85, 69, 0, 0, 0 },
            { 74, 85, 78, 0, 0, 0 }, { 75, 65, 0, 0, 0, 0 }, { 75, 65, 73, 0, 0, 0 },
            { 75, 65, 78, 0, 0, 0 }, { 75, 65, 78, 71, 0, 0 }, { 75, 65, 79, 0, 0, 0 },
            { 75, 69, 0, 0, 0, 0 }, { 75, 69, 73, 0, 0, 0 }, { 75, 69, 78, 0, 0, 0 },
            { 75, 69, 78, 71, 0, 0 }, { 75, 79, 78, 71, 0, 0 }, { 75, 79, 85, 0, 0, 0 },
            { 75, 85, 0, 0, 0, 0 }, { 75, 85, 65, 0, 0, 0 }, { 75, 85, 65, 73, 0, 0 },
            { 75, 85, 65, 78, 0, 0 }, { 75, 85, 65, 78, 71, 0 }, { 75, 85, 73, 0, 0, 0 },
            { 75, 85, 78, 0, 0, 0 }, { 75, 85, 79, 0, 0, 0 }, { 76, 65, 0, 0, 0, 0 },
            { 76, 65, 73, 0, 0, 0 }, { 76, 65, 78, 0, 0, 0 }, { 76, 65, 78, 71, 0, 0 },
            { 76, 65, 79, 0, 0, 0 }, { 76, 69, 0, 0, 0, 0 }, { 76, 69, 73, 0, 0, 0 },
            { 76, 69, 78, 71, 0, 0 }, { 76, 73, 0, 0, 0, 0 }, { 76, 73, 65, 0, 0, 0 },
            { 76, 73, 65, 78, 0, 0 }, { 76, 73, 65, 78, 71, 0 }, { 76, 73, 65, 79, 0, 0 },
            { 76, 73, 69, 0, 0, 0 }, { 76, 73, 78, 0, 0, 0 }, { 76, 73, 78, 71, 0, 0 },
            { 76, 73, 85, 0, 0, 0 }, { 76, 79, 78, 71, 0, 0 }, { 76, 79, 85, 0, 0, 0 },
            { 76, 85, 0, 0, 0, 0 }, { 76, 85, 65, 78, 0, 0 }, { 76, 85, 69, 0, 0, 0 },
            { 76, 85, 78, 0, 0, 0 }, { 76, 85, 79, 0, 0, 0 }, { 77, 0, 0, 0, 0, 0 },
            { 77, 65, 0, 0, 0, 0 }, { 77, 65, 73, 0, 0, 0 }, { 77, 65, 78, 0, 0, 0 },
            { 77, 65, 78, 71, 0, 0 }, { 77, 65, 79, 0, 0, 0 }, { 77, 69, 0, 0, 0, 0 },
            { 77, 69, 73, 0, 0, 0 }, { 77, 69, 78, 0, 0, 0 }, { 77, 69, 78, 71, 0, 0 },
            { 77, 73, 0, 0, 0, 0 }, { 77, 73, 65, 78, 0, 0 }, { 77, 73, 65, 79, 0, 0 },
            { 77, 73, 69, 0, 0, 0 }, { 77, 73, 78, 0, 0, 0 }, { 77, 73, 78, 71, 0, 0 },
            { 77, 73, 85, 0, 0, 0 }, { 77, 79, 0, 0, 0, 0 }, { 77, 79, 85, 0, 0, 0 },
            { 77, 85, 0, 0, 0, 0 }, { 78, 65, 0, 0, 0, 0 }, { 78, 65, 73, 0, 0, 0 },
            { 78, 65, 78, 0, 0, 0 }, { 78, 65, 78, 71, 0, 0 }, { 78, 65, 79, 0, 0, 0 },
            { 78, 69, 0, 0, 0, 0 }, { 78, 69, 73, 0, 0, 0 }, { 78, 69, 78, 0, 0, 0 },
            { 78, 69, 78, 71, 0, 0 }, { 78, 73, 0, 0, 0, 0 }, { 78, 73, 65, 78, 0, 0 },
            { 78, 73, 65, 78, 71, 0 }, { 78, 73, 65, 79, 0, 0 }, { 78, 73, 69, 0, 0, 0 },
            { 78, 73, 78, 0, 0, 0 }, { 78, 73, 78, 71, 0, 0 }, { 78, 73, 85, 0, 0, 0 },
            { 78, 79, 78, 71, 0, 0 }, { 78, 79, 85, 0, 0, 0 }, { 78, 85, 0, 0, 0, 0 },
            { 78, 85, 65, 78, 0, 0 }, { 78, 85, 69, 0, 0, 0 }, { 78, 85, 79, 0, 0, 0 },
            { 79, 0, 0, 0, 0, 0 }, { 79, 85, 0, 0, 0, 0 }, { 80, 65, 0, 0, 0, 0 },
            { 80, 65, 73, 0, 0, 0 }, { 80, 65, 78, 0, 0, 0 }, { 80, 65, 78, 71, 0, 0 },
            { 80, 65, 79, 0, 0, 0 }, { 80, 69, 73, 0, 0, 0 }, { 80, 69, 78, 0, 0, 0 },
            { 80, 69, 78, 71, 0, 0 }, { 80, 73, 0, 0, 0, 0 }, { 80, 73, 65, 78, 0, 0 },
            { 80, 73, 65, 79, 0, 0 }, { 80, 73, 69, 0, 0, 0 }, { 80, 73, 78, 0, 0, 0 },
            { 80, 73, 78, 71, 0, 0 }, { 80, 79, 0, 0, 0, 0 }, { 80, 79, 85, 0, 0, 0 },
            { 80, 85, 0, 0, 0, 0 }, { 81, 73, 0, 0, 0, 0 }, { 81, 73, 65, 0, 0, 0 },
            { 81, 73, 65, 78, 0, 0 }, { 81, 73, 65, 78, 71, 0 }, { 81, 73, 65, 79, 0, 0 },
            { 81, 73, 69, 0, 0, 0 }, { 81, 73, 78, 0, 0, 0 }, { 81, 73, 78, 71, 0, 0 },
            { 81, 73, 79, 78, 71, 0 }, { 81, 73, 85, 0, 0, 0 }, { 81, 85, 0, 0, 0, 0 },
            { 81, 85, 65, 78, 0, 0 }, { 81, 85, 69, 0, 0, 0 }, { 81, 85, 78, 0, 0, 0 },
            { 82, 65, 78, 0, 0, 0 }, { 82, 65, 78, 71, 0, 0 }, { 82, 65, 79, 0, 0, 0 },
            { 82, 69, 0, 0, 0, 0 }, { 82, 69, 78, 0, 0, 0 }, { 82, 69, 78, 71, 0, 0 },
            { 82, 73, 0, 0, 0, 0 }, { 82, 79, 78, 71, 0, 0 }, { 82, 79, 85, 0, 0, 0 },
            { 82, 85, 0, 0, 0, 0 }, { 82, 85, 65, 78, 0, 0 }, { 82, 85, 73, 0, 0, 0 },
            { 82, 85, 78, 0, 0, 0 }, { 82, 85, 79, 0, 0, 0 }, { 83, 65, 0, 0, 0, 0 },
            { 83, 65, 73, 0, 0, 0 }, { 83, 65, 78, 0, 0, 0 }, { 83, 65, 78, 71, 0, 0 },
            { 83, 65, 79, 0, 0, 0 }, { 83, 69, 0, 0, 0, 0 }, { 83, 69, 78, 0, 0, 0 },
            { 83, 69, 78, 71, 0, 0 }, { 83, 72, 65, 0, 0, 0 }, { 83, 72, 65, 73, 0, 0 },
            { 83, 72, 65, 78, 0, 0 }, { 83, 72, 65, 78, 71, 0 }, { 83, 72, 65, 79, 0, 0 },
            { 83, 72, 69, 0, 0, 0 }, { 83, 72, 69, 78, 0, 0 }, { 83, 72, 69, 78, 71, 0 },
            { 83, 72, 73, 0, 0, 0 }, { 83, 72, 79, 85, 0, 0 }, { 83, 72, 85, 0, 0, 0 },
            { 83, 72, 85, 65, 0, 0 }, { 83, 72, 85, 65, 73, 0 }, { 83, 72, 85, 65, 78, 0 },
            { 83, 72, 85, 65, 78, 71 }, { 83, 72, 85, 73, 0, 0 }, { 83, 72, 85, 78, 0, 0 },
            { 83, 72, 85, 79, 0, 0 }, { 83, 73, 0, 0, 0, 0 }, { 83, 79, 78, 71, 0, 0 },
            { 83, 79, 85, 0, 0, 0 }, { 83, 85, 0, 0, 0, 0 }, { 83, 85, 65, 78, 0, 0 },
            { 83, 85, 73, 0, 0, 0 }, { 83, 85, 78, 0, 0, 0 }, { 83, 85, 79, 0, 0, 0 },
            { 84, 65, 0, 0, 0, 0 }, { 84, 65, 73, 0, 0, 0 }, { 84, 65, 78, 0, 0, 0 },
            { 84, 65, 78, 71, 0, 0 }, { 84, 65, 79, 0, 0, 0 }, { 84, 69, 0, 0, 0, 0 },
            { 84, 69, 78, 71, 0, 0 }, { 84, 73, 0, 0, 0, 0 }, { 84, 73, 65, 78, 0, 0 },
            { 84, 73, 65, 79, 0, 0 }, { 84, 73, 69, 0, 0, 0 }, { 84, 73, 78, 71, 0, 0 },
            { 84, 79, 78, 71, 0, 0 }, { 84, 79, 85, 0, 0, 0 }, { 84, 85, 0, 0, 0, 0 },
            { 84, 85, 65, 78, 0, 0 }, { 84, 85, 73, 0, 0, 0 }, { 84, 85, 78, 0, 0, 0 },
            { 84, 85, 79, 0, 0, 0 }, { 87, 65, 0, 0, 0, 0 }, { 87, 65, 73, 0, 0, 0 },
            { 87, 65, 78, 0, 0, 0 }, { 87, 65, 78, 71, 0, 0 }, { 87, 69, 73, 0, 0, 0 },
            { 87, 69, 78, 0, 0, 0 }, { 87, 69, 78, 71, 0, 0 }, { 87, 79, 0, 0, 0, 0 },
            { 87, 85, 0, 0, 0, 0 }, { 88, 73, 0, 0, 0, 0 }, { 88, 73, 65, 0, 0, 0 },
            { 88, 73, 65, 78, 0, 0 }, { 88, 73, 65, 78, 71, 0 }, { 88, 73, 65, 79, 0, 0 },
            { 88, 73, 69, 0, 0, 0 }, { 88, 73, 78, 0, 0, 0 }, { 88, 73, 78, 71, 0, 0 },
            { 88, 73, 79, 78, 71, 0 }, { 88, 73, 85, 0, 0, 0 }, { 88, 85, 0, 0, 0, 0 },
            { 88, 85, 65, 78, 0, 0 }, { 88, 85, 69, 0, 0, 0 }, { 88, 85, 78, 0, 0, 0 },
            { 89, 65, 0, 0, 0, 0 }, { 89, 65, 78, 0, 0, 0 }, { 89, 65, 78, 71, 0, 0 },
            { 89, 65, 79, 0, 0, 0 }, { 89, 69, 0, 0, 0, 0 }, { 89, 73, 0, 0, 0, 0 },
            { 89, 73, 78, 0, 0, 0 }, { 89, 73, 78, 71, 0, 0 }, { 89, 79, 0, 0, 0, 0 },
            { 89, 79, 78, 71, 0, 0 }, { 89, 79, 85, 0, 0, 0 }, { 89, 85, 0, 0, 0, 0 },
            { 89, 85, 65, 78, 0, 0 }, { 89, 85, 69, 0, 0, 0 }, { 89, 85, 78, 0, 0, 0 },
            { 90, 65, 0, 0, 0, 0 }, { 90, 65, 73, 0, 0, 0 }, { 90, 65, 78, 0, 0, 0 },
            { 90, 65, 78, 71, 0, 0 }, { 90, 65, 79, 0, 0, 0 }, { 90, 69, 0, 0, 0, 0 },
            { 90, 69, 73, 0, 0, 0 }, { 90, 69, 78, 0, 0, 0 }, { 90, 69, 78, 71, 0, 0 },
            { 90, 72, 65, 0, 0, 0 }, { 90, 72, 65, 73, 0, 0 }, { 90, 72, 65, 78, 0, 0 },
            { 90, 72, 65, 78, 71, 0 }, { 90, 72, 65, 79, 0, 0 }, { 90, 72, 69, 0, 0, 0 },
            { 90, 72, 69, 78, 0, 0 }, { 90, 72, 69, 78, 71, 0 }, { 90, 72, 73, 0, 0, 0 },
            { 90, 72, 79, 78, 71, 0 }, { 90, 72, 79, 85, 0, 0 }, { 90, 72, 85, 0, 0, 0 },
            { 90, 72, 85, 65, 0, 0 }, { 90, 72, 85, 65, 73, 0 }, { 90, 72, 85, 65, 78, 0 },
            { 90, 72, 85, 65, 78, 71 }, { 90, 72, 85, 73, 0, 0 }, { 90, 72, 85, 78, 0, 0 },
            { 90, 72, 85, 79, 0, 0 }, { 90, 73, 0, 0, 0, 0 }, { 90, 79, 78, 71, 0, 0 },
            { 90, 79, 85, 0, 0, 0 }, { 90, 85, 0, 0, 0, 0 }, { 90, 85, 65, 78, 0, 0 },
            { 90, 85, 73, 0, 0, 0 }, { 90, 85, 78, 0, 0, 0 }, { 90, 85, 79, 0, 0, 0 }, };

    /** First and last Chinese character with known Pinyin according to zh collation */
    private static final String FIRST_PINYIN_UNIHAN = "\u963F";
    private static final String LAST_PINYIN_UNIHAN = "\u84D9";
    /** The first Chinese character in Unicode block */
    private static final char FIRST_UNIHAN = '\u3400';
    private static final Collator COLLATOR = Collator.getInstance(Locale.CHINA);

    private static HanziToPinyin sInstance;
    private final boolean mHasChinaCollator;

    public static class Token {
        /**
         * Separator between target string for each source char
         */
        public static final String SEPARATOR = " ";

        public static final int LATIN = 1;
        public static final int PINYIN = 2;
        public static final int UNKNOWN = 3;

        public Token() {
        }

        public Token(int type, String source, String target) {
            this.type = type;
            this.source = source;
            this.target = target;
        }

        /**
         * Type of this token, ASCII, PINYIN or UNKNOWN.
         */
        public int type;
        /**
         * Original string before translation.
         */
        public String source;
        /**
         * Translated string of source. For Han, target is corresponding Pinyin. Otherwise target is
         * original string in source.
         */
        public String target;
    }

    protected HanziToPinyin(boolean hasChinaCollator) {
        mHasChinaCollator = hasChinaCollator;
    }

    public static HanziToPinyin getInstance() {
        synchronized (HanziToPinyin.class) {
            if (sInstance != null) {
                return sInstance;
            }
            // Check if zh_CN collation data is available
            final Locale locale[] = Collator.getAvailableLocales();
            for (int i = 0; i < locale.length; i++) {
                if (locale[i].equals(Locale.CHINA)) {
                    // Do self validation just once.
                    if (DEBUG) {
                        Log.d(TAG, "Self validation. Result: " + doSelfValidation());
                    }
                    sInstance = new HanziToPinyin(true);
                    return sInstance;
                }
            }
            Log.w(TAG, "There is no Chinese collator, HanziToPinyin is disabled");
            sInstance = new HanziToPinyin(false);
            return sInstance;
        }
    }

    /**
     * Validate if our internal table has some wrong value.
     *
     * @return true when the table looks correct.
     */
    private static boolean doSelfValidation() {
        char lastChar = UNIHANS[0];
        String lastString = Character.toString(lastChar);
        for (char c : UNIHANS) {
            if (lastChar == c) {
                continue;
            }
            final String curString = Character.toString(c);
            int cmp = COLLATOR.compare(lastString, curString);
            if (cmp >= 0) {
                Log.e(TAG, "Internal error in Unihan table. " + "The last string \"" + lastString
                        + "\" is greater than current string \"" + curString + "\".");
                return false;
            }
            lastString = curString;
        }
        return true;
    }

    private Token getToken(char character) {
        Token token = new Token();
        final String letter = Character.toString(character);
        token.source = letter;
        int offset = -1;
        int cmp;
        if (character < 256) {
            token.type = Token.LATIN;
            token.target = letter;
            return token;
        } else if (character < FIRST_UNIHAN) {
            token.type = Token.UNKNOWN;
            token.target = letter;
            return token;
        } else {
            cmp = COLLATOR.compare(letter, FIRST_PINYIN_UNIHAN);
            if (cmp < 0) {
                token.type = Token.UNKNOWN;
                token.target = letter;
                return token;
            } else if (cmp == 0) {
                token.type = Token.PINYIN;
                offset = 0;
            } else {
                cmp = COLLATOR.compare(letter, LAST_PINYIN_UNIHAN);
                if (cmp > 0) {
                    token.type = Token.UNKNOWN;
                    token.target = letter;
                    return token;
                } else if (cmp == 0) {
                    token.type = Token.PINYIN;
                    offset = UNIHANS.length - 1;
                }
            }
        }

        token.type = Token.PINYIN;
        if (offset < 0) {
            int begin = 0;
            int end = UNIHANS.length - 1;
            while (begin <= end) {
                offset = (begin + end) / 2;
                final String unihan = Character.toString(UNIHANS[offset]);
                cmp = COLLATOR.compare(letter, unihan);
                if (cmp == 0) {
                    break;
                } else if (cmp > 0) {
                    begin = offset + 1;
                } else {
                    end = offset - 1;
                }
            }
        }
        if (cmp < 0) {
            offset--;
        }
        StringBuilder pinyin = new StringBuilder();
        for (int j = 0; j < PINYINS[offset].length && PINYINS[offset][j] != 0; j++) {
            pinyin.append((char) PINYINS[offset][j]);
        }
        token.target = pinyin.toString();
        return token;
    }

    /**
     * Convert the input to a array of tokens. The sequence of ASCII or Unknown characters without
     * space will be put into a Token, One Hanzi character which has pinyin will be treated as a
     * Token. If these is no China collator, the empty token array is returned.
     */
    public ArrayList<Token> get(final String input) {
        ArrayList<Token> tokens = new ArrayList<Token>();
        if (!mHasChinaCollator || TextUtils.isEmpty(input)) {
            // return empty tokens.
            return tokens;
        }
        final int inputLength = input.length();
        final StringBuilder sb = new StringBuilder();
        int tokenType = Token.LATIN;
        // Go through the input, create a new token when
        // a. Token type changed
        // b. Get the Pinyin of current charater.
        // c. current character is space.
        for (int i = 0; i < inputLength; i++) {
            final char character = input.charAt(i);
            if (character == ' ') {
                if (sb.length() > 0) {
                    addToken(sb, tokens, tokenType);
                }
            } else if (character < 256) {
                if (tokenType != Token.LATIN && sb.length() > 0) {
                    addToken(sb, tokens, tokenType);
                }
                tokenType = Token.LATIN;
                sb.append(character);
            } else if (character < FIRST_UNIHAN) {
                if (tokenType != Token.UNKNOWN && sb.length() > 0) {
                    addToken(sb, tokens, tokenType);
                }
                tokenType = Token.UNKNOWN;
                sb.append(character);
            } else {
                Token t = getToken(character);
                if (t.type == Token.PINYIN) {
                    if (sb.length() > 0) {
                        addToken(sb, tokens, tokenType);
                    }
                    tokens.add(t);
                    tokenType = Token.PINYIN;
                } else {
                    if (tokenType != t.type && sb.length() > 0) {
                        addToken(sb, tokens, tokenType);
                    }
                    tokenType = t.type;
                    sb.append(character);
                }
            }
        }
        if (sb.length() > 0) {
            addToken(sb, tokens, tokenType);
        }
        return tokens;
    }

    private void addToken(
            final StringBuilder sb, final ArrayList<Token> tokens, final int tokenType) {
        String str = sb.toString();
        tokens.add(new Token(tokenType, str, str));
        sb.setLength(0);
    }
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值