項目中有聊天模塊,需要用到打開activity的時候初始化聊天記錄的情況。大致情況如下:
輔助類:ChatSQLiteHelper 在第一次時會調用oncreate方法(判斷的標准是schedule.db里面會存儲是否已經新建過,若沒有,則會調用onCreate,只會調用一次)
package com.example.qurenwu.chat; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.database.sqlite.SQLiteDatabase.CursorFactory; public class ChatSQLiteHelper extends SQLiteOpenHelper{ //調用父類構造器 public ChatSQLiteHelper(Context context, String name, CursorFactory factory, int version) { super(context, name, factory, version); } /** * 當數據庫首次創建時執行該方法,一般將創建表等初始化操作放在該方法中執行. * 重寫onCreate方法,調用execSQL方法創建表 * */ @Override public void onCreate(SQLiteDatabase db) { db.execSQL("CREATE TABLE chat (id INTEGER PRIMARY KEY,"+ "user_id varchar(64), "+ "friend_id varchar(64), "+ "contentChat varchar(255), typeChat varchar(8), "+ "postdateChat DATETIME, "+ "isreadChat integer,"+ "ismineChat integer NOT NULL DEFAULT (0),"+ "deleteChat integer);"); } //當打開數據庫時傳入的版本號與當前的版本號不同時會調用該方法 @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } }
以下是使用方法(由於趕時間,下面的代碼都是在activity中的頁面代碼中)
package com.example.qurenwu.qurenwu_2.chat; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.SocketException; import java.net.SocketTimeoutException; import java.net.UnknownHostException; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import android.app.Activity; import android.content.ContentValues; import android.content.Intent; import android.database.ContentObserver; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.graphics.Bitmap; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.Message; import android.util.DisplayMetrics; import android.util.Log; import android.view.KeyEvent; import android.view.View; import android.view.View.OnClickListener; import android.view.WindowManager; import android.widget.Button; import android.widget.EditText; import android.widget.ImageView; import android.widget.ListView; import android.widget.SimpleAdapter; import android.widget.Toast; import com.example.qurenwu.qurenwu_2.R; import com.example.qurenwu.qurenwu_2.custom.GotaskGlobalVal; import com.example.qurenwu.qurenwu_2.thread.UserHttpThread; import org.json.JSONException; import org.json.JSONObject; public class ChatPageActivity extends Activity implements OnClickListener{ private ImageView back; private Button mBtnSend; private EditText mEditTextContent; private ListView mTalkView; private ChatMsgAdapter mAdapter; private List<ChatMsgEntity> mDataArrays = new ArrayList<ChatMsgEntity>(); private GotaskGlobalVal globalVal; UserHttpThread userHttpThread; private String myuser_id,friend_id; private String friend_head_image_url; //對方頭像 private String my_head_image_url; //我的頭像 DisplayMetrics dm; int dmwidth; SocketThread st; public DataInputStream dis = null; public DataOutputStream dos = null; Handler handler; SQLiteOpenHelper openHelper; private final int REV_MSG = 1; //接收消息 private final int REQUEST_MINE_HEADURL = 2; //獲取我的頭像url public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_chat_page); getWindow().setSoftInputMode( WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); //軟鍵盤 //獲取手機屏幕像素 dm = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(dm); dmwidth = dm.widthPixels; globalVal = (GotaskGlobalVal) getApplicationContext(); back = (ImageView)findViewById(R.id.back); back.setOnClickListener(this); //接收好友對象資料 Intent intent = getIntent(); friend_id = intent.getStringExtra("friend_id"); friend_head_image_url = intent.getStringExtra("friend_head_image"); //獲取對方頭像url my_head_image_url = intent.getStringExtra("my_head_image"); //獲取自己頭像url Log.v("獲取頭像:","對方頭像"+friend_head_image_url+";我的頭像:"+my_head_image_url); myuser_id = globalVal.GetUserID(); handler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case REV_MSG://處理接收到的消息 String str = msg.obj.toString(); try { int forend = str.indexOf(config.PROTOCOL_FOR_END); //解析str if(forend>0) { String fromname = str.substring(str.indexOf(config.PROTOCOL_COME) + 1, str.indexOf(config.PROTOCOL_COME_END)); String forname = str.substring(str.indexOf(config.PROTOCOL_FOR) + 1, str.indexOf(config.PROTOCOL_FOR_END)); String _date = str.substring(str.indexOf(config.PROTOCOL_DATE) + 1, str.indexOf(config.PROTOCOL_DATE_END)); String forchat = str.substring(str.indexOf(config.PROTOCOL_DATE_END) + 1); ChatMsgEntity entity = new ChatMsgEntity(); entity.setDate(_date); entity.setName(fromname); entity.setText(forchat); entity.setMsgType(true); mDataArrays.add(entity); mAdapter.notifyDataSetChanged(); mTalkView.setSelection(mDataArrays.size()-1); Log.v("Handle接收到的消息",forchat); } } catch (Exception ex) {} break; case REQUEST_MINE_HEADURL: break; } } }; initView(); //1、從本地sqlite數據庫獲取歷史數據 //首次進入,先把聊天記錄調出 initdb(); readChat(); //2、socket連接服務器 chatContent(); new Thread(new ReceiveThread()).start(); } //初始化界面 public void initView() { mTalkView = (ListView) findViewById(R.id.listview); mBtnSend = (Button) findViewById(R.id.btn_send); mBtnSend.setOnClickListener(this); mEditTextContent = (EditText) findViewById(R.id.et_sendmessage); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.back: openHelper.close(); finish(); break; case R.id.btn_send: send(); break; } } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK && ((FaceRelativeLayout) findViewById(R.id.FaceRelativeLayout)) .hideFaceView()) { Log.v("onKeyDown","表情FaceRelativeLayout"); return true; } return super.onKeyDown(keyCode, event); } private void send() { String contString = mEditTextContent.getText().toString(); //更新界面 if (contString.length() > 0) { ChatMsgEntity entity = new ChatMsgEntity(); entity.setDate(getDate()); entity.setMsgType(false); entity.setText(contString); entity.setHeadImg(my_head_image_url); mDataArrays.add(entity); mAdapter.notifyDataSetChanged(); mEditTextContent.setText(""); mTalkView.setSelection(mTalkView.getCount() - 1); } //發送socket消息 DateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); String date = df.format(new Date()); try { if(dos!=null){ dos.writeUTF(config.PROTOCOL_KEY+config.PROTOCOL_FOR + friend_id + config.PROTOCOL_FOR_END +myuser_id+"end;"+contString); //將發送的消息存入本地 ContentValues con = new ContentValues(); con.put("fromChat", friend_id); con.put("nameChat", myuser_id); con.put("contentChat", contString); con.put("typeChat", "text"); con.put("postdateChat", date); con.put("isreadChat", "1"); con.put("ismineChat", "1"); con.put("deleteChat", "0"); //getContentResolver().insert(DataChangeProvider.CONTENT_URI, con); //保存到本地sqlite SQLiteDatabase db=openHelper.getReadableDatabase(); ContentValues values = new ContentValues(); values.put("user_id",myuser_id); values.put("friend_id",friend_id); values.put("contentChat",contString); values.put("typeChat","text"); values.put("postdateChat",date); values.put("isreadChat",1); values.put("ismineChat",1); db.insert("chat",null,values); db.close(); }else{ Toast.makeText(ChatPageActivity.this, "連接超時,服務器未開放或IP錯誤,dos is null", Toast.LENGTH_LONG).show(); } }catch (SocketTimeoutException e) { System.out.println("連接超時,服務器未開放或IP錯誤"+e.getMessage()); Toast.makeText(ChatPageActivity.this, "連接超時,服務器未開放或IP錯誤", Toast.LENGTH_SHORT).show(); e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block System.out.println("連接超時,服務器未開放或IP錯誤"+e.getMessage()); Toast.makeText(ChatPageActivity.this, "連接超時,服務器未開放或IP錯誤", Toast.LENGTH_SHORT).show(); e.printStackTrace(); } } private String getDate() { Calendar c = Calendar.getInstance(); String year = String.valueOf(c.get(Calendar.YEAR)); String month = String.valueOf(c.get(Calendar.MONTH)); String day = String.valueOf(c.get(Calendar.DAY_OF_MONTH) + 1); String hour = String.valueOf(c.get(Calendar.HOUR_OF_DAY)); String mins = String.valueOf(c.get(Calendar.MINUTE)); StringBuffer sbBuffer = new StringBuffer(); sbBuffer.append(year + "-" + month + "-" + day + " " + hour + ":" + mins); return sbBuffer.toString(); } //子線程連接服務器socket public void chatContent(){ new Thread(){ public void run () { try { st = new SocketThread(); st.SocketStart(config.SERVER_IP, config.SERVER_PORT, friend_id); if(st.isConnected()){ dos = st.getDOS(); dis = st.getDIS(); dos.writeUTF(config.PROTOCOL_KEY+config.PROTOCOL_ONLINE+myuser_id); dos.flush(); dos.writeUTF(config.PROTOCOL_KEY+config.PROTOCOL_WAIT+myuser_id); dos.flush(); } }catch (UnknownHostException e) { System.out.println("連接失敗"); Toast.makeText(ChatPageActivity.this, "連接失敗", Toast.LENGTH_SHORT).show(); e.printStackTrace(); }catch (SocketTimeoutException e) { System.out.println("連接超時,服務器未開放或IP錯誤"); Toast.makeText(ChatPageActivity.this, "連接超時,服務器未開放或IP錯誤", Toast.LENGTH_SHORT).show(); e.printStackTrace(); }catch (IOException e) { System.out.println("連接失敗"); e.printStackTrace(); } } }.start(); } private class ReceiveThread implements Runnable { public void run() { try { while (true) { try { String str = dis.readUTF(); Message msg = new Message(); msg.what = REV_MSG; msg.obj = str; handler.sendMessage(msg); } catch (NullPointerException ex) {} } } catch (SocketException e) { System.out.println("SocketException"); } catch (IOException e) { e.printStackTrace(); } } } private void RequestUserInfo(String user_id) { Map<String,String> param = new HashMap<String, String>(); param.put("datatype","5"); param.put("user_id",user_id); userHttpThread = new UserHttpThread(handler,param,REQUEST_MINE_HEADURL); new Thread(userHttpThread).start(); } private void initdb() { //准備數據庫,存取聊天記錄 openHelper=new ChatSQLiteHelper(this,"chat.db",null,1) ; } private void readChat(){ String _date; String _text; String _isreadChat; String _ismineChat; //0:對方的消息 1:自己發送的消息 boolean _isComMeg = true; //獲取數據庫中的信息 SQLiteDatabase db=openHelper.getReadableDatabase(); String sql="select contentChat,postdateChat,isreadChat,ismineChat from chat where user_id=? and friend_id=?"; Cursor c = db.rawQuery(sql,new String[]{globalVal.GetUserID(),friend_id}); while(c.moveToNext()){ _text=c.getString(0); _date=c.getString(1); _isreadChat=c.getString(2); _ismineChat=c.getString(3); Log.v("ceshi", _text+_date+_isreadChat); ChatMsgEntity entity = new ChatMsgEntity(); entity.setText(_text); entity.setDate(_date); if(_ismineChat!=null && _ismineChat.equals("0")){_isComMeg= false;} entity.setMsgType(_isComMeg); entity.setHeadImg(_isComMeg?my_head_image_url:friend_head_image_url); mDataArrays.add(entity); } mAdapter = new ChatMsgAdapter(this, mDataArrays,mTalkView); mTalkView.setAdapter(mAdapter); mTalkView.setSelection(mTalkView.getCount() - 1); db.close(); } }
說一下我當時遇到的問題:
1、sqlite出現no such table chat ,原因:沒有調用ChatSQLiteHelper的Oncreate方法,因為我在activity中有重寫了ChatSQLiteHelper的Oncreate方法
如下:
openHelper=new ChatSQLiteHelper(this,"chat.db",null,1) { public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } public void onCreate(SQLiteDatabase db) { //這里是空的,什么事情都沒做,所以也就不會新建chat表了 } }
2、出現 android_meta***忘記了,反正糾結在數據庫的路徑這一塊,下面大略寫出來對比一下
之前錯誤的寫法:
private SQLiteDatabase openDateBase(String dbFile) //dbFile是我自己命名的一個路徑:/data/data/你的報名/databases/chat.db { File file = new File(dbFile); if (!file.exists()) { // // 打開raw中得數據庫文件,獲得stream流 InputStream stream = this.mContext.getResources().openRawResource(R.raw.chat); //該目錄下也放了一個自己導出來的chat.db,所以不能這么做,自己都暈了 try { // 將獲取到的stream 流寫入道data中 FileOutputStream outputStream = new FileOutputStream(dbFile); .... } } }
現在的寫法:
openHelper=new ChatSQLiteHelper(this,"chat.db",null,1) ; //直接調用,默認ChatSQLiteHelper創建的路徑,真實地址應該是:/data/data/你的報名/databases/ 這個目錄下面