編輯:關於Android編程
本節引言:
Android入門系列已經寫了大半了,學習了這麼多理論知識,不練下手怎麼行呢?
在實際的開發中我們會遇到更多的問題,同時也能加固我們的基礎知識!鑒於
筆者的水平有限,該項目,面對的是初學者,各位大牛路過不喜勿噴!好吧說下第一個
練手項目吧,前幾天中秋節今天又是教師節,各種祝福短信滿天飛,手打再群發,條條
短信一個樣,沒意思!直接用別人弄好的短信群發,別人又不知道你是誰,起碼加個:
親愛的XXX.我是隔壁老王,.....別人起碼知道你是誰把!好了,廢話不多說,開始app
的開發吧!
ps:目前app的基本功能已經實現,效果圖如下,如果有需要可以進行下載
到後面會逐步完善相關功能:
效果圖:
參考代碼下載:
源碼下載
正文:
創建數據庫文件:有兩個表,分別為存儲聯系人的表contacts和存儲節日祝福語的表festival
可以直接使用SQLite Expert或者其他SQLite的可視化工具創建表,可以代碼創建或者手動創建
代碼創建的話執行以下語句生成數據庫表:
CREATE TABLE festival(sentence_id INTEGER PRIMARY KEY AUTOINCREMENT,detail)
CREATE TABLE contacts(_id INTEGER PRIMARY KEY,pname,pnumber,pstate)
接著對節日表進行數據的錄入,結束的表結構如下:
festival表:
contacts表:
在完成上述創建數據庫的步驟後,接著我們需要把數據庫文件復制到assert目錄下
這裡我們要做什麼呢?
在應用啟動的時候我們需要判斷data/data/<包名>/database下有沒有我們的數據庫文件
如果不存在的話,我們需要通過代碼將數據庫文件導入到指定目錄下!
①先定義我們的數據庫名稱以及包名常量:
public static String dbName=my.db;//數據庫的名字 private static String DATABASE_PATH=/data/data/com.jay.example.festivalsmshelper/databases/;
②接著定義判斷是數據庫文件是否存在的方法:
public boolean checkDataBase(){ SQLiteDatabase checkDB = null; try{ String databaseFilename = DATABASE_PATH+dbName; checkDB =SQLiteDatabase.openDatabase(databaseFilename, null, SQLiteDatabase.OPEN_READONLY); }catch(SQLiteException e){ } if(checkDB!=null){ checkDB.close(); } return checkDB !=null?true:false; }
public void copyDataBase() throws IOException{ String databaseFilenames =DATABASE_PATH+dbName; File dir = new File(DATABASE_PATH); if(!dir.exists())//判斷文件夾是否存在,不存在就新建一個 dir.mkdir(); FileOutputStream os = null; try{ os = new FileOutputStream(databaseFilenames);//得到數據庫文件的寫入流 }catch(FileNotFoundException e){ e.printStackTrace(); } InputStream is = MainActivity.this.getAssets().open(my.db); byte[] buffer = new byte[4096]; int count = 0; try{ while((count=is.read(buffer))>0){ os.write(buffer, 0, count); os.flush(); } }catch(IOException e){e.printStackTrace();} is.close(); os.close(); }
boolean dbExist = checkDataBase(); if(dbExist){} else{//不存在就把assert裡的數據庫寫入手機 try{ copyDataBase(); }catch(IOException e){throw new Error(復制數據庫出錯);} }
如圖就說明數據庫文件復制完畢,是僅僅有一個my.db文件而已!後面那個my.do-journal是因為執行了
其他的操作生成的!
這裡的話我們讀取的僅僅是聯系人的目錄,並不包括sim卡中的聯系人哦!
這塊就涉及到了我們前面所學的使用系統提供的ContentProvider了!
我們先把系統提供的聯系人的數據庫文件找出來瞅瞅吧!
打開文件浏覽器:data/data/com.android.providers.contacts/databases
下面的contacts2.db文件就是存儲系統聯系人的數據庫文件了:
導出以後查看幾個重要的基本表,以及相關字段:
contacts表
data表
phone_look_up表
raw_contact表
以上四個就是我們要留意的四個表了
好了,說下我們要獲取的數據:聯系人id,姓名,一個電話號碼
於是我們定義一個類GetPhone類並定義一個讀取聯系人的方法,將讀到數據存儲到list集合中:
代碼如下:
public static ListgetPerson(Context context) { List persons = new ArrayList (); ContentResolver cr = context.getContentResolver(); Cursor cursor = cr.query(ContactsContract.Contacts.CONTENT_URI,null, null, null, null); while(cursor.moveToNext()){ Person person = new Person(); //獲取聯系人id String contatId = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID)); person.setId(Integer.parseInt(contatId)); //獲取聯系人姓名 String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)); person.setName(name); //因為一個聯系人的電話號碼可能有幾個,但我們這裡僅僅是獲取一個就夠了,所以就不循環遍歷了 Cursor phones = context.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID+=+contatId, null, null); phones.moveToFirst(); String num = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)); person.setNumber(num); person.setState(-1); persons.add(person); phones.close(); } cursor.close(); return persons; }
該方法的參數是一個Person的對象,我們使用ContentValues來存儲從person取出的不同數據!
再調用db.insert(contacts,null,contentValue)將記錄插入到contacts表中
代碼:
public void insert(Person person){ SQLiteDatabase db = dbOpenHelper.getWritableDatabase(); ContentValues values = new ContentValues(); values.put(_id, person.getId()); values.put(pname, person.getName()); values.put(pnumber, person.getNumber()); values.put(pstate, person.getState()); db.insert(contacts, null, values); }
怕數據太多,出現卡住的情況,加個進度條,用戶看著沒那麼不爽!
再new一個線程,一秒鐘後讓進度條消失,第一個界面消失,通過intent跳轉
到第二個界面中!
代碼:
//加個進度條,數據太多可能卡住不好,用戶看著不爽 final ProgressDialog dialog = ProgressDialog.show(this, 提示, 讀取聯系人中, false, true); GetContactsService getContacts = new GetContactsService(getApplicationContext()); Listpersons = GetPerson.getPerson(MainActivity.this); Cursor cursor = getContacts.query(select count(*) from contacts, null); cursor.moveToFirst(); //判斷聯系人數目是否發生變更,沒變更的話就不用調用下面的for循環了 if(persons.size() != cursor.getInt(0)) { for(Person p : persons) { System.out.println(p.toString()); getContacts.insert(p); } } //設置讓圓形進度條過一秒後消失,以及第一個界面消失,跳轉到第二個界面 new Thread() { public void run() { try { sleep(1000); } catch (InterruptedException e) {e.printStackTrace();} dialog.dismiss(); Intent it = new Intent(getApplicationContext(), ChooseActivity.class); startActivity(it); finish(); }; }.start();
將my.db文件導出後可以看到contacts表的data已經有數據了,就完成了
另外記得還有個Person類別漏了,定義四個屬性:id,name,number,state(記錄是否已經發送)
這裡就不給出了,另外要創建出第二個Activity完成Intent的跳轉哦!不然可是會報錯的!
1.判斷app中的數據庫文件是否存在?不存在的話如何使用輸入流將文件寫入到相應目錄下
2.如何獲得assert裡的文件,從而獲得輸入流對象;
3.哪裡可以找到系統保存聯系人的數據庫;相關表以及字段的了解!
讀取表中我們需要的聯系人信息!
4.調用database的insert()方法插入ContentValues類型的數據
5.獲得數據庫表有多少條記錄的方法:
Cursor cursor = getContacts.query(select count(*) from contacts, null);
cursor.moveToFirst();
cursor.getInt(0);
6.獲取List集合中的數據元素:list.size();
好了這一節就暫且到這裡吧,如果對本文有什麼建議,批評的,歡迎指出!
不慎感激!項目的代碼會隨著後面深入慢慢完善的!
android.support.v7.widget.RecyclerViewandroid.support.v7.widget.LinearLayoutManageran
性能問題一般歸結為3類:1.UI卡頓和穩定性,這類問題用戶可直接感知,最為重要。2.內存問題,內存問題主要表現為內存洩漏。如果存在內存洩漏,應用會不斷消耗內存,容易導致頻
一、簡介Android基於Linux平台的開源手機操作系統。二、原理既然是Linux,那就應該支持linux的各種命令行,高度的可配置,但實驗發現Android是Goog
開發設計搞了一個帶圓形進度的進度條,在GitHub上逛了一圈,發現沒有,自己撸吧。先看界面效果:主要思路是寫一個繼承ProgressBar的自定義View,不廢話,直接上