自制的通讯录APP(SQLite的应用)
来源:互联网 发布:明底线知敬畏演讲稿 编辑:程序博客网 时间:2024/06/11 18:41
转载请附上本文链接并标明作者。
这几天做了一个通讯录APP,主要难点是自己在SQlite建表而不是读取手机联系人的信息以及对SearchView的应用,另外还添加了生日提醒功能,由于时间关系并没有太多注释,可读性一般,也相对粗糙。建议在了解SQliteOpenHelper,Cursor,SimpleCursorAdapter,ListView和adapter等知识之后阅读,会容易理解。适合练手,有什么问题请留言指正,欢迎大牛指点。
(SDK:4.3,开发工具:AS1.5)
1.建立一个ContactDBhelper继承自SQliteOpenHelper类
public class ContactDBHelper extends SQLiteOpenHelper { private static final String DB_NAME = "CONTACT_DB"; private static final String TBL_NAME = "CONTACT_TBL"; //"_id"很重要,最好加上.name存放姓名,number存放电话,千万别和我一样存int型!还有month和day分别对应月和日,用data型,这里用int型是巨大失误导致后面判断日期是十分麻烦. private static final String CREAT_TBL ="create table CONTACT_TBL(_id INTEGER PRIMARY KEY AUTOINCREMENT,name string(20),number int,month int,day int)"; private static SQLiteDatabase db; public static final int VERSION = 1; public ContactDBHelper(Context context) { super(context,DB_NAME, null,VERSION); } public void onCreate(SQLiteDatabase db){ this.db = db; db.execSQL(CREAT_TBL); } public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){ } public void close(){ if(db != null){ db.close(); } }}
2.点击添加进入addActivity来添加用户,主要用到了ContentValues.put方法。
public class addActivity extends ActionBarActivity { private EditText iname; private EditText inumber; private EditText imonth; private EditText iday; private Button ensure,cancel; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.add); iname = (EditText)findViewById(R.id.input_name); inumber = (EditText)findViewById(R.id.input_number); imonth = (EditText)findViewById(R.id.input_month); iday = (EditText)findViewById(R.id.input_day); ensure =(Button)findViewById(R.id.action_ensure); cancel = (Button)findViewById(R.id.action_cancel); ensure.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { ContactDBHelper contactDBHelper = new ContactDBHelper(getBaseContext()); SQLiteDatabase db = contactDBHelper.getWritableDatabase(); ContentValues cv = new ContentValues(); cv.put("name", iname.getText().toString()); cv.put("number", Integer.parseInt(inumber.getText().toString())); cv.put("month", Integer.parseInt(imonth.getText().toString())); cv.put("day", Integer.parseInt(iday.getText().toString())); db.insert("CONTACT_TBL",null,cv); addActivity.this.finish(); } }); cancel.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { addActivity.this.finish(); } }); }}
3.点击ListView上的用户名跳转到ModifyActivity,详情页的概念。点击修改可以修改联系人信息,并单击完成保存,原理是用update更新表。
public class ModifyActivity extends ActionBarActivity { private EditText rname; private EditText rnumber; private EditText rmonth; private EditText rday; private Button change,stop; private ImageButton phone,msg; private int position; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_modify); rname = (EditText)findViewById(R.id.read_name); rnumber = (EditText)findViewById(R.id.read_number); rmonth = (EditText)findViewById(R.id.read_month); rday = (EditText)findViewById(R.id.read_day); change =(Button)findViewById(R.id.action_change); stop = (Button)findViewById(R.id.action_stop); phone = (ImageButton)findViewById(R.id.phone); msg = (ImageButton)findViewById(R.id.msg); Bundle bundle = this.getIntent().getExtras(); position = bundle.getInt("position"); ContactDBHelper contactDBHelper = new ContactDBHelper(getBaseContext()); SQLiteDatabase dbr = contactDBHelper.getReadableDatabase(); Cursor cursor= dbr.query("CONTACT_TBL", null, null, null, null, null, null); cursor.moveToPosition(position); rname.setText(cursor.getString(cursor.getColumnIndex("name"))); rnumber.setText(cursor.getString(cursor.getColumnIndex("number"))); rmonth.setText(cursor.getString(cursor.getColumnIndex("month"))); rday.setText(cursor.getString(cursor.getColumnIndex("day"))); rname.setEnabled(false); rnumber.setEnabled(false); rmonth.setEnabled(false); rday.setEnabled(false); change.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { ContactDBHelper contactDBHelper = new ContactDBHelper(getBaseContext()); SQLiteDatabase db = contactDBHelper.getWritableDatabase(); Cursor cursor = db.query("CONTACT_TBL", null, null, null, null, null, null); cursor.moveToPosition(position); int itemID = cursor.getInt(cursor.getColumnIndex("_id")); String[] which = new String[]{itemID + ""}; ContentValues cv = new ContentValues(); cv.put("name", rname.getText().toString()); cv.put("number", Integer.parseInt(rnumber.getText().toString())); cv.put("month", Integer.parseInt(rmonth.getText().toString())); cv.put("day", Integer.parseInt(rday.getText().toString())); db.update("CONTACT_TBL", cv, "_id=?", which); ModifyActivity.this.finish(); } }); stop.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { ModifyActivity.this.finish(); } }); phone.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + rnumber.getText())); ModifyActivity.this.startActivity(intent); } }); msg.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Uri sms = Uri.parse("smsto:"+rnumber.getText()); Intent intent = new Intent(Intent.ACTION_SENDTO, sms); ModifyActivity.this.startActivity(intent); } }); } public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); switch (id) { case R.id.action_modify: rname.setEnabled(true); rnumber.setEnabled(true); rmonth.setEnabled(true); rday.setEnabled(true); } return super.onOptionsItemSelected(item); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_modify, menu); return true; }}
4.自定义Myadapter用于SearchView。
public class Myadapter extends BaseAdapter implements Filterable { private Context context; private List<String> data , copyData ; public Myadapter(Context context, List<String> data) { super(); this.context = context; this.data = data; copyData = data ; } @Override public int getCount() { return data.size() ; } @Override public Object getItem(int position) { return data.get(position) ; } @Override public long getItemId(int position) { return position ; } @Override public View getView(int position, View convertView, ViewGroup parent) { View view ; if(null == convertView) { view = LayoutInflater.from(context).inflate(android.R.layout.simple_list_item_1, null) ; } else { view = convertView ; } TextView tv = (TextView) view.findViewById(android.R.id.text1) ; tv.setText(data.get(position)) ; return view ; } private Filter myFilter ; @Override public Filter getFilter() { if(null == myFilter) { myFilter = new MyFilter() ; } return myFilter ; } class MyFilter extends Filter{ // 定义过滤规则 protected FilterResults performFiltering(CharSequence constraint) { List<String> filterData = new ArrayList<String>() ; if(constraint != null && constraint.toString().trim().length() > 0) { String key = constraint.toString().trim().toLowerCase() ; for (String item : copyData) { if(item.toLowerCase().indexOf(key) != -1) { filterData.add(item) ; } } } else { //如果搜索框为空,就恢复原始数据 filterData = copyData ; } FilterResults results = new FilterResults() ; results.values = filterData ; results.count = filterData.size() ; return results ; } @Override protected void publishResults(CharSequence constraint, FilterResults results) { data = (List<String>) results.values ; if(results.count > 0) { notifyDataSetChanged() ; } else { notifyDataSetInvalidated() ; } } } ;}
5.实现搜索框的方法是:点击EditText跳转到SearchActivity,利用SearchActivity里的SearchView来实现。此时就需要实例化前面自定义的Myadapter类。
public class SearchActivity extends ActionBarActivity { private static final String TBL_NAME = "CONTACT_TBL"; private static ContactDBHelper contactDBHelper; private static SQLiteDatabase dbRead; private static SQLiteDatabase dbWrite; private static Cursor cursor; private static ContentValues cv; public SearchView searchView; public ListView listView2; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_search); searchView = (SearchView)findViewById(R.id.search_view); listView2 = (ListView)findViewById(R.id.listview2); listView2.setTextFilterEnabled(true) ; contactDBHelper = new ContactDBHelper(this); dbWrite = contactDBHelper.getWritableDatabase(); dbRead = contactDBHelper.getReadableDatabase(); cursor = dbRead.query(TBL_NAME, null, null, null, null, null, null); //遍历表得到data,用于实例化Myadapter List<String> data = new ArrayList<String>(); if(cursor!=null&&cursor.moveToFirst()){ do{ data.add(cursor.getString(cursor.getColumnIndex("name"))); }while(cursor.moveToNext()); }; Myadapter myadapter = new Myadapter(SearchActivity.this,data); listView2.setAdapter(myadapter); searchView.setIconifiedByDefault(false); searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { public boolean onQueryTextSubmit(String s) { return true; } @Override public boolean onQueryTextChange(String s) { if (s != null && s.length() > 0) { listView2.setFilterText(s); } else { listView2.clearTextFilter(); } return true; } }); //设置listview点击事件 listView2.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) { cursor.moveToPosition(position); Intent intent = new Intent(SearchActivity.this, ModifyActivity.class); Bundle bundle = new Bundle(); bundle.putInt("position", position); intent.putExtras(bundle); startActivity(intent); } }); //设置listview长按事件 listView2.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { @Override public boolean onItemLongClick(AdapterView<?> adapterView, View view, final int position, long l) { new AlertDialog.Builder(SearchActivity.this) .setTitle("是否删除该联系人?") .setNegativeButton("取消", null) .setPositiveButton("确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { cursor.moveToPosition(position); int itemID = cursor.getInt(cursor.getColumnIndex("_id")); String[] which = new String[]{itemID + ""}; dbWrite.delete(TBL_NAME, "_id=?", which); refreshListView(); } }).show(); return true; } }); } public void refreshListView(){ cursor = dbRead.query(TBL_NAME, null, null, null, null, null, null); List<String> data = new ArrayList<String>(); if(cursor!=null&&cursor.moveToFirst()){ do{ data.add(cursor.getString(cursor.getColumnIndex("name"))); }while(cursor.moveToNext()); }; Myadapter myadapter = new Myadapter(SearchActivity.this,data); listView2.setAdapter(myadapter); } @Override protected void onResume(){ super.onResume(); refreshListView(); }}
6.最后是主活动。长按LiteView上的Item先弹出是否删除的对话框,选择是删除。删除主要靠delete()方法。
public class MainActivity extends ActionBarActivity { public static final String TBL_NAME = "CONTACT_TBL"; public static ContactDBHelper contactDBHelper; public static SQLiteDatabase dbRead; public static SQLiteDatabase dbWrite; public static Cursor cursor; public static ContentValues cv; public ListView listView; public EditText editText; public SimpleCursorAdapter listAdapter; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); listView = (ListView) findViewById(R.id.listview); editText = (EditText)findViewById(R.id.edittext); editText.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(MainActivity.this,SearchActivity.class); startActivity(intent); } }); contactDBHelper = new ContactDBHelper(this); dbWrite = contactDBHelper.getWritableDatabase();// cv = new ContentValues();//// cv.put("name", "jonsnow");// cv.put("number", 9257);// cv.put("month", 3);// cv.put("day",10);// dbWrite.insert(TBL_NAME, null, cv);////// cv.put("name", "james");// cv.put("number", 3154);// cv.put("month", 6);// cv.put("day",12);// dbWrite.insert(TBL_NAME, null, cv);////// cv.put("name", "curry");// cv.put("number", 8080);// cv.put("month", 4);// cv.put("day",25);// dbWrite.insert(TBL_NAME, null, cv); //dbWrite.delete(TBL_NAME,null,null); dbRead = contactDBHelper.getReadableDatabase(); cursor = dbRead.query(TBL_NAME, null, null, null, null, null, null); String[] from = new String[]{"name"}; int[] to = new int[]{R.id.name}; //SimpleCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to, int flags). //五个参数的实例化SimpleCursorAdapter方法已经被废弃,然而笔者将第六个参数flag设为0,却始终无法编译成功,查了很多资料仍无法解决错误,无奈之下只好使用老方法。有知道为何的朋友若能告知,感激不尽。 listAdapter = new SimpleCursorAdapter(this, R.layout.list_item, cursor, from, to); listView.setAdapter(listAdapter); listView.setTextFilterEnabled(true); //设置listview点击事件 listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) { Cursor c = listAdapter.getCursor(); c.moveToPosition(position); Intent intent = new Intent(MainActivity.this, ModifyActivity.class); Bundle bundle = new Bundle(); bundle.putInt("position", position); intent.putExtras(bundle); startActivity(intent); } }); //设置listview长按事件 listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { @Override public boolean onItemLongClick(AdapterView<?> adapterView, View view, final int position, long l) { new AlertDialog.Builder(MainActivity.this) .setTitle("是否删除该联系人?") .setNegativeButton("取消", null) .setPositiveButton("确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { ; Cursor c = listAdapter.getCursor(); c.moveToPosition(position); int itemID = c.getInt(c.getColumnIndex("_id")); String[] which = new String[]{itemID + ""}; dbWrite.delete(TBL_NAME, "_id=?", which); refreshListView(); } }).show(); return true; } }); BirthRemind(); } public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); switch (id) { case R.id.action_add: Intent intent = new Intent(MainActivity.this,addActivity.class); startActivity(intent);// break;// case R.id.action_about:// AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);// builder.setTitle("关于我们")// .setMessage("团队:Espirit\n"+"Blog:http://blog.csdn.net/qq_28625603")// .show(); } return super.onOptionsItemSelected(item); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; } public void refreshListView(){ cursor = dbRead.query(TBL_NAME, null, null, null, null, null, null); listAdapter.changeCursor(cursor); } @Override protected void onResume(){ super.onResume(); refreshListView(); } //生日提醒功能 protected void BirthRemind(){ //获取当前时间 Calendar c = Calendar.getInstance(); int month =c.get(Calendar.MONTH)+1; int day =c.get(Calendar.DAY_OF_MONTH); Cursor cursor = dbWrite.query(TBL_NAME, new String[]{"month", "day"}, null, null, null, null, null); //这里就是强烈建议大家用data型存储日期的原因。我利用四个List才确定了日期。如果处理大一点的数据,不敢想象。当初建表的时候没考虑周全,果然还是naive。 //主要逻辑就是先把所有人的生日月份拿出来和当前月比较,把相同的月份的索引拿出来放入新的list里。由于月和日是一起录入到两个list里的,所以索引是能对上号的。然后根据索引读取存放所有人的day里的数据,放在心的list里,最后如果list里有符合当前日的元素,就利用通知栏通知。 //因为建表的问题和时间关系,并没有读取姓名并且显示到通知栏上,实现起来相信也不难。这里点击通知栏也只有回到主页面而不是详情页。 List<Integer> listmonth = new ArrayList<Integer>(); List<Integer> listday = new ArrayList<Integer>(); while(cursor.moveToNext()){ listmonth.add(Integer.parseInt(cursor.getString(cursor.getColumnIndex("month")))); listday.add( Integer.parseInt(cursor.getString(cursor.getColumnIndex("day")))); } int lm = listmonth.size(); List<Integer> matchm = new ArrayList<>(); for(int i = 0;i<lm;i++) { if(listmonth.get(i)==month){ matchm.add(i); continue; } } int mm = matchm.size(); List<Integer> matchd = new ArrayList<>(); for(int i=0; i<mm;i++){ matchd.add(listday.get(matchm.get(i))); } if(matchd.contains(day)){ //通知栏通知 NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); int icon = android.R.drawable.stat_notify_chat; long when = System.currentTimeMillis() + 2000; Notification n = new Notification(icon, "您有一个联系人今天生日", when); n.defaults = Notification.DEFAULT_SOUND; n.flags |= Notification.FLAG_AUTO_CANCEL; Intent openintent = new Intent(this,MainActivity.class); PendingIntent pi = PendingIntent.getActivity(this, 0, openintent, PendingIntent.FLAG_CANCEL_CURRENT); n.setLatestEventInfo(this, "生日提醒", "XXX今天生日,快去给TA送上祝福吧", pi); nm.notify(0, n); } }}
layout文件就不放了。
效果如下:
主页面,点击添加跳转至添加联系人页面。点击用户名跳转至联系人详情页,长按用户名呼出删除提示。
添加联系人页面。
删除提示框,点击确认即可删除用户。
在详情页点击修改可修改,单击电话或者短信图标分别对应通话或短信功能。
点击搜索框跳转到搜索页面。搜索页面也可以进入详情页和进行删除联系人操作。
- 自制的通讯录APP(SQLite的应用)
- 自制的简易通讯录
- app内置通讯录的实现
- 自制的分割线+应用
- 【安卓自带数据库的简单应用】自制账号集APP
- Android JPush (通讯录好友,是该应用app,则发送一条提示消息,点击通知,跳进对应的页面)
- 自制通讯录
- app应用运行中,自动监测手机通讯录的改变,达到同步更新
- 自制的android多渠道应用打包工具--RyApkTool(1)
- 自制的android多渠道应用打包工具--RyApkTool(2)
- 自制应用层协议的编写
- SQLite 的应用实例
- android SQLite的应用
- SQLite的简单应用
- sqlite的应用实例
- SQLite数据库的应用
- SQLite的应用
- SQLite的多线程应用
- hbase 基本命令
- C++中的继承
- Android开发指南--0 总览
- poj3258 二分(连续区间求和)
- U3D自定义滑动面板ViewPager
- 自制的通讯录APP(SQLite的应用)
- Redis-sds源码剖析第一天
- android studio无法设置java jdk
- 黑马程序员——基本数据类型总结
- Saiku 二次开发效果的演示视频
- UISlider
- UDP 编程中的sendto() 与recvfrom()解析(转)
- 数据库分词查询的优缺点以及英文和中文各自的分词方法(二)
- MySQL添加用户、删除用户与授权