选择、搜索国家码&数据库表转Json文件
一、应用场景
首先,
废
话不多说了,有图有真像,这里先上几张效果图:
第一张截图来自facebook,第二张来自我们的应用
后面3张来自我这次要分享的效果截图
由此可以看出,这部分的内容在实际的App应用开发中,还是经常用到的。
比如我们在注册时,
可以选择手机号注册,而手机号是有国家或地区码归属的,
而国家和地区码相对较多,需要提供
用户搜索功能的需求。
二、Demo工程目录
然后在AndroidManifest.xml中加入SDcard读写权限:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
三
、Demo源码文件
1. activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.mobile.countrycode.MainActivity"
tools:ignore="MergeRootFrame" >
<Button
android:id="@+id/select_country_code"
android:layout_width="match_parent"
android:layout_height="44dp"
android:text="选择国家 "
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:background="#440000ff"
android:gravity="center"
android:textSize="20sp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:orientation="horizontal" >
<EditText
android:id="@+id/search_country_code"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_gravity="center_vertical"
android:gravity="center"
android:layout_weight="1"
android:hint="搜索内容" />
<Button
android:id="@+id/search"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_gravity="center_vertical"
android:visibility="visible"
android:layout_weight="4"
android:gravity="center"
android:text="搜索" />
</LinearLayout>
<ListView android:id="@+id/list_country_code"
android:layout_width="match_parent"
android:visibility="visible"
android:layout_height="match_parent">
</ListView>
</LinearLayout>
2、adapter_country_code.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:orientation="horizontal" >
<TextView
android:id="@+id/country_name"
android:text="中国"
android:layout_weight="1"
android:gravity="left|center_vertical"
android:textSize="18sp"
android:layout_width="match_parent"
android:layout_height="40dp" />
<TextView
android:id="@+id/country_code"
android:text="+86"
android:layout_weight="1"
android:gravity="right|center_vertical"
android:layout_width="match_parent"
android:textSize="18sp"
android:layout_height="40dp" />
</LinearLayout>
3、MainActivity.java
package com.mobile.countrycode;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import android.app.Activity;
import android.content.res.AssetManager;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.os.Environment;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.mobile.countrycode.adapters.CountryCodeAdapter;
import com.mobile.countrycode.db.dao.CountryCodeDao;
import com.mobile.countrycode.domain.CountryCode;
import com.mobile.countrycode.utils.FileUtils;
public class MainActivity extends Activity {
private static final String TAG = MainActivity.class.getSimpleName();
private SQLiteDatabase db;
private static final String externalPath = Environment
.getExternalStorageDirectory().getAbsolutePath() + File.separator;
private static final int BUFFERED_SIZE = 1024;
private ListView listView;
private CountryCodeAdapter adapter;
private List<CountryCode> countryCodeInfos;
private List<CountryCode> searchInfos;
private Button search;
private EditText searchCountryCode;
private Button selectCountryCode;
private String databasePath;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE); //无title
getWindow().setFlags(
WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN); //全屏
setContentView(R.layout.activity_main);
listView = (ListView) findViewById(R.id.list_country_code);
searchCountryCode = (EditText) findViewById(R.id.search_country_code);
search = (Button) findViewById(R.id.search);
selectCountryCode = (Button) findViewById(R.id.select_country_code);
initData(); //初始化一些数据
}
private void initData() {
// "/data/data/com.mobile.countrycode/files/area.db"
Log.i(TAG, "数据库文件路径是: " + getFilesDir() + File.separator + "area.db");
databasePath = getFilesDir() + File.separator + "area.db";
copyDB("area.db");
db = SQLiteDatabase.openDatabase(databasePath, null, SQLiteDatabase.OPEN_READONLY);
countryCodeInfos = CountryCodeDao.findAll(databasePath);
adapter = new CountryCodeAdapter(countryCodeInfos, this);
listView.setAdapter(adapter);
search.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String keyword = searchCountryCode.getText().toString().trim();
if(TextUtils.isEmpty(keyword)) {
Toast.makeText(getApplicationContext(), "搜索关键字不能为空", Toast.LENGTH_LONG).show();
countryCodeInfos = CountryCodeDao.findAll(databasePath);
adapter = new CountryCodeAdapter(countryCodeInfos, getApplicationContext());
} else {
searchInfos = CountryCodeDao.fuzzySearch(databasePath, keyword);
adapter = new CountryCodeAdapter(searchInfos, getApplicationContext());
}
listView.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
});
selectCountryCode.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
selectCountryCode.setText("将国家码信息转Json文件");
tableInfo2JsonFile();
}
});
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
CountryCode countryCode = countryCodeInfos.get(position);
int country_code = countryCode.getCountry_code();
String country_name = countryCode.getCountry_name_cn();
Toast.makeText(getApplicationContext(), "+" + country_code + " " + country_name,
Toast.LENGTH_LONG).show();
}
});
}
/**
* 拷贝资产目录下的数据库文件
* @param fileName 数据库名
*/
private void copyDB(String fileName) {
File file = new File(getFilesDir(), fileName);
if(file.exists() && file.length() > 0){
Log.i(TAG, "数据库文件已经拷贝过了,无需重复拷贝");
} else {
try {
// 数据库文件只需要拷贝一次,如果已经拷贝成功了。以后就不需要重复的拷贝了
AssetManager am = getAssets();
InputStream is = am.open(fileName);
// 创建一个文件 /data/data/包名/files/area.db
FileOutputStream fos = new FileOutputStream(file);
byte[] buffer = new byte[BUFFERED_SIZE];
int len = 0;
while ((len = is.read(buffer)) != -1) {
fos.write(buffer, 0, len);
}
is.close();
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 数据库表信息转成json文件
*/
public void tableInfo2JsonFile(){
Toast.makeText(this, "将国家码数据库表信息转Json", Toast.LENGTH_LONG).show();
JsonArray array = new JsonArray();
for(CountryCode countryCode : CountryCodeDao.findAll(databasePath)){
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("country_id", countryCode.getCountry_id());
jsonObject.addProperty("country_code", countryCode.getCountry_code());
jsonObject.addProperty("country_name_en", countryCode.getCountry_name_en());
jsonObject.addProperty("country_name_cn", countryCode.getCountry_name_cn());
jsonObject.addProperty("ab", countryCode.getAb());
array.add(jsonObject); // 生成json数组
}
try {
// writeFile(jsonObject.toString());
// writeFile(array.toString());
writeFile(array);// 写到SDCard
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 为了提高写入的效率,使用了字符流的缓冲区。
* 创建了一个字符写入流的缓冲区对象,并和指定要被缓冲的流对象相关联。
* @param array
* @throws IOException
*/
private void writeFile(JsonArray array) throws IOException {
FileWriter fw = new FileWriter(FileUtils.getFilePath(externalPath, "countryCode.json"),true);
BufferedWriter bufw = new BufferedWriter(fw);
//使用缓冲区中的方法将数据写入到缓冲区中。
bufw.write(array.toString());
bufw.newLine();
//使用缓冲区中的方法,将数据刷新到目的地文件中去。
bufw.flush();
//关闭缓冲区,同时关闭了fw流对象
bufw.close();
}
@Override
protected void onDestroy() {
super.onDestroy();
db.close();
}
}
4、CountryCodeAdapter.java
package com.mobile.countrycode.adapters;
import java.util.List;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import com.mobile.countrycode.R;
import com.mobile.countrycode.domain.CountryCode;
public class CountryCodeAdapter extends BaseAdapter {
private List<CountryCode> countryCodeInfos;
private Context context;
public CountryCodeAdapter(List<CountryCode> countryCodeInfos,
Context context) {
this.countryCodeInfos = countryCodeInfos;
this.context = context;
}
@Override
public int getCount() {
return countryCodeInfos.size();
}
@Override
public CountryCode getItem(int position) {
return countryCodeInfos.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (null == convertView) {
holder = new ViewHolder();
convertView = LayoutInflater.from(context).inflate(R.layout.adapter_country_code, null);
holder.countryName = (TextView) convertView.findViewById(R.id.country_name);
holder.countryCode = (TextView) convertView.findViewById(R.id.country_code);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
CountryCode countryCode = getItem(position);
holder.countryName.setText(countryCode.getCountry_name_cn());
holder.countryCode.setText("+"+String.valueOf(countryCode.getCountry_code()));
return convertView;
}
static class ViewHolder {
TextView countryName;
TextView countryCode;
}
}
5、CountryCode.java
package com.mobile.countrycode.domain;
public class CountryCode {
private int country_id; //序号id
private int country_code; //国家码
private String country_name_en; //英文名
private String country_name_cn; //中文名
private String ab; //字母简称
public int getCountry_id() {
return country_id;
}
public void setCountry_id(int country_id) {
this.country_id = country_id;
}
public int getCountry_code() {
return country_code;
}
public void setCountry_code(int country_code) {
this.country_code = country_code;
}
public String getCountry_name_en() {
return country_name_en;
}
public void setCountry_name_en(String country_name_en) {
this.country_name_en = country_name_en;
}
public String getCountry_name_cn() {
return country_name_cn;
}
public void setCountry_name_cn(String country_name_cn) {
this.country_name_cn = country_name_cn;
}
public String getAb() {
return ab;
}
public void setAb(String ab) {
this.ab = ab;
}
@Override
public String toString() {
return "CountryCode [country_id=" + country_id + ", country_code="
+ country_code + ", country_name_en=" + country_name_en
+ ", country_name_cn=" + country_name_cn + ", ab=" + ab + "]";
}
}
6、CountryCodeDao.java
package com.mobile.countrycode.db.dao;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import com.mobile.countrycode.domain.CountryCode;
public class CountryCodeDao {
/*
* 判断是关键字否为整数
* @param keyword 传入的字符串
* @return 是整数返回true,否则返回false
*/
public static boolean isInteger(String keyword) {
Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");
return pattern.matcher(keyword).matches();
}
/**
* 模糊查找
* @param keyword
* @return
*/
public static List<CountryCode> fuzzySearch(String databasePath, String keyword){
String sql = "select country_code,country_name_cn,country_name_en,ab from country ";
SQLiteDatabase db = SQLiteDatabase.openDatabase(databasePath, null, SQLiteDatabase.OPEN_READONLY);
if (isInteger(keyword)) {
int searchNum = Integer.parseInt(keyword);
sql = sql + "where country_code like '%" + searchNum + "%'" + "order by country_code,ab";
// db.query("country", new String[]{"country_code", "country_name_cn", "country_name_en", "ab"},
// "country_code like '%?%'", new String[]{keyword} , null, null, "country_code,ab");
} else {
sql = sql + "where country_name_cn like '%" + keyword + "%'" + "order by country_code,ab";
}
Cursor cursor = db.rawQuery(sql, null);
List<CountryCode> infos = new ArrayList<CountryCode>();
while(cursor.moveToNext()) {
CountryCode countryCode = new CountryCode();
int country_code = cursor.getInt(cursor.getColumnIndex("country_code"));
String country_name_en = cursor.getString(cursor.getColumnIndex("country_name_en"));
String country_name_cn = cursor.getString(cursor.getColumnIndex("country_name_cn"));
String ab = cursor.getString(cursor.getColumnIndex("ab")).trim();
countryCode.setCountry_code(country_code);
countryCode.setCountry_name_en(country_name_en.trim());
countryCode.setCountry_name_cn(country_name_cn.trim());
countryCode.setAb(ab.trim());
infos.add(countryCode);
}
return infos;
}
/**
* 获取全部的国家代码信息
* @return
*/
public static List<CountryCode> findAll(String databasePath){
SQLiteDatabase db = SQLiteDatabase.openDatabase(databasePath, null, SQLiteDatabase.OPEN_READONLY);
String sql = "select country_id,country_code,country_name_en,country_name_cn,ab from country";
Cursor cursor = db.rawQuery(sql, null);
// Cursor cursor = db.query("country", new String[]{"country_id", "country_code", "country_name_en",
// "country_name_cn", "ab"}, null, null, null, null, null);
List<CountryCode> infos = new ArrayList<CountryCode>();
while(cursor.moveToNext()){
CountryCode countryCode = new CountryCode();
int country_id = cursor.getInt(cursor.getColumnIndex("country_id"));
int country_code = cursor.getInt(cursor.getColumnIndex("country_code"));
String country_name_en = cursor.getString(cursor.getColumnIndex("country_name_en"));
String country_name_cn = cursor.getString(cursor.getColumnIndex("country_name_cn"));
String ab = cursor.getString(cursor.getColumnIndex("ab"));
countryCode.setCountry_id(country_id);
countryCode.setCountry_code(country_code);
countryCode.setCountry_name_en(country_name_en.trim());
countryCode.setCountry_name_cn(country_name_cn.trim());
countryCode.setAb(ab.trim());
infos.add(countryCode);
}
cursor.close();
db.close();
return infos;
}
}
7、FileUtils.java
package com.mobile.countrycode.utils;
import java.io.File;
public class FileUtils {
/**
* 根据文件路径和文件名返回文件对象
* @param filePath
* @param fileName
* @return
*/
public static File getFilePath(String filePath, String fileName) {
File file = null;
makeRootDirectory(filePath);
try {
file = new File(filePath + fileName);
} catch (Exception e) {
e.printStackTrace();
}
return file;
}
/**
* 根据文件路径判断是否创建文件目录
* @param filePath
*/
public static void makeRootDirectory(String filePath) {
File file = null;
try {
file = new File(filePath);
if (!file.exists()) {
file.mkdir();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
四、Demo功能解释
1、可以按关键字,也可以靠数字搜索模糊搜索出包含此关键字的国家名和国家码。
2、按顶部的title(其实是一个按钮),可以将Sqlite数据库表信息转成Json文件。
资源链接:
1)Demo源码
注:生成的countryCode.json在SDCard上的格式是一行的,可以到开源中国
JSON在线解析工具 格式化。
area.db里还包含全国的省市信息。