openfire+asmack搭建的安卓即时通讯(七) 15.5.27
本地化之章!
往期传送门:
1.http://www.cnblogs.com/lfk-dsk/p/4398943.html
2.http://www.cnblogs.com/lfk-dsk/p/4411625.html
3.http://www.cnblogs.com/lfk-dsk/p/4412126.html
4.http://www.cnblogs.com/lfk-dsk/p/4413693.html
5.http://www.cnblogs.com/lfk-dsk/p/4419418.html
6.http://www.cnblogs.com/lfk-dsk/p/4433319.html
真没想到这东西居然还会写到第七篇,很多亲们的反馈和鼓励给了我很大的动力啊,最近正好朋友也在做这个东西,但是我们用一样的库和后端做的东西居然不一样(他用这个做了联网弹幕!),不过确实发现了一些问题比如asmack的库内容参差不齐,很多提供方法都不一样,看来使用者们都或多或少的对源码进行了一些修改,都变得乱糟糟的呢!
这里就提供一下我自己用的asmack库吧,省的大家用的不一样:https://files.cnblogs.com/files/lfkdsk/asmack.zip
这次的博文先从完成的效果开始吧,这个并不是最终稿,因为虽然完成了很多的功能啊,但是还有一些问题,比如接收数据没用广播啊,监听的ChatListener没放在server里啊,好友系统并不完善啊,很多的东西还没有完成,到时候还要根据这些东西进行一些修改,但是现在需要的功能已经够用了,接着的那些东西也不过是要应用asmack库里的东西而已了,好了先上效果图:
(1.首先登录界面增加了Ip的选项,更具有Spark的android版的感觉,通用性强了,不过我之后要是想上线让大家用可能会删掉)
(2.现在不打开具体的聊天窗口,程序也不会蹦了,因为原来是直接向listview里面添加数据,可是listview还没初始化所以会崩)
(3.打开具体的useractivity就会取出原来的数据然后还有新打印的出来的)
(4.信息由于是走数据库了,所以分发也不会想原来一样出错了)
(5.我不想用传统的通知栏,那个用户能禁用,哈哈哈哈哈哈哈,我用了定制的Toast,在桌面的时候接到消息就会弹出一个Toast提示!)
好了这就是我们本次要达成的效果,让我们一个一个来!
1.首先从主界面的输入IP开始:
1 <TableRow> 2 <TextView 3 android:textColor="#ffc2c6c6" 4 android:layout_height="wrap_content" 5 android:text="Ip"/> 6 <EditText 7 android:id="@+id/login_ip" 8 android:hint="Input your Ip" 9 android:maxLines="1" 10 android:layout_height="wrap_content" 11 /> 12 </TableRow>
先在TableLayout里添加。
静态数据类里添加:
1 //ip名称 2 public static String My_Ip = "";
主活动的添加:
ip = (EditText) findViewById(R.id.login_ip);
check_init()函数里添加:
1 private void checkbox_init() {//checkbox判断函数 2 //判断记住密码多选框的状态 3 if(sp.getBoolean("ISCHECK", false)) 4 { 5 //设置默认是记录密码状态 6 check_save.setChecked(true); 7 ip.setText(sp.getString("USER_IP", "")); 8 name.setText(sp.getString("USER_NAME","")); 9 password.setText(sp.getString("PASSWORD","")); 10 //判断自动登陆多选框状态 11 if(sp.getBoolean("AUTO_ISCHECK", false)) 12 { 13 //设置默认是自动登录状态 14 check_auto.setChecked(true); 15 //跳转界面 16 //account=sp.getString("USER_NAME",""); 17 //pwd=sp.getString("PASSWORD",""); 18 Log.i("======================"+account,pwd+"==================================="); 19 accountLogin(); 20 } 21 } 22 } 23 private void setCheck_save(){ 24 if(check_save.isChecked()) 25 { 26 //记住用户名、密码、 27 editor = sp.edit(); 28 editor.putString("USER_IP", user.My_Ip); 29 editor.putString("USER_NAME", account); 30 editor.putString("PASSWORD",pwd); 31 editor.apply(); 32 } 33 }
这个是把Ip添加进记录。
修改登录的方法:
1 private void accountLogin() { 2 new Thread() { 3 public void run() { 4 user.My_Ip = ((EditText)findViewById(R.id.login_ip)) 5 .getText().toString(); 6 account = ((EditText) findViewById(R.id.login_name)) 7 .getText().toString(); 8 pwd = ((EditText) findViewById(R.id.login_password)).getText() 9 .toString(); 10 boolean is = ConnecMethod.login(account, pwd); 11 if (is) { 12 insHandler.sendEmptyMessage(1); 13 // 将用户名保存 14 user.UserName = account+"@lfkdsk/Spark 2.6.3"; 15 user.UserName_= account; 16 setCheck_save(); 17 } else { 18 insHandler.sendEmptyMessage(0); 19 } 20 } 21 }.start(); 22 }
但是要是逐层的为函数添加参数,然后无限的传参也是一种不太现实的方法,所以我们在XMpp连接的地方直接调用静态存储的IP:
1 public static boolean openConnection() { 2 try { 3 connConfig = new ConnectionConfiguration(user.My_Ip, 5222); 4 // 设置登录状态为离线 5 connConfig.setSendPresence(false); 6 // 断网重连 7 connConfig.setReconnectionAllowed(true); 8 con = new XMPPConnection(connConfig); 9 con.connect(); 10 return true; 11 } catch (Exception e) { 12 13 } 14 return false; 15 }
这样我们登陆的时候就能手动指定ip或者是域名了,增强了通用性。
2.本地化数据的具体操作:
1.新建一个类作为本地数据库的模版:
1 package com.lfk.webim.appli; 2 3 import android.util.Log; 4 5 /** 6 * Created by Administrator on 2015/5/26. 7 */ 8 public class TalkLogs { 9 private String ID = "_id"; //数据库主键,自增 10 private String With_Id ="with_id"; //和谁聊天 11 private String Logs = "talklogs"; //聊天记录 12 private String If_read = "_ifread"; //是否已读 13 private String dbname; //数据表名---为用户名,即user.UserName_ 14 private String CREAT_DB = ""; //数据库新建的语句 15 16 public TalkLogs(String dbname){ 17 this.dbname = dbname; 18 giveanameto(dbname); 19 Log.e("dbname=====", this.dbname); 20 Log.e("dbname参数=====",dbname); 21 } 22 private void giveanameto(String dbname){ 23 CREAT_DB = "CREATE TABLE if not exists "+dbname+"(" 24 +this.ID +" integer primary key autoincrement," 25 +this.With_Id+"," 26 +this.If_read+" integer," 27 + this.Logs+")"; 28 } 29 public String returnAString(){ 30 Log.e("CREAT_DB===========",CREAT_DB); 31 return CREAT_DB; 32 } 33 }
1 package com.lfk.webim.appli; 2 3 import android.content.Context; 4 import android.database.sqlite.SQLiteDatabase; 5 import android.database.sqlite.SQLiteOpenHelper; 6 import android.widget.Toast; 7 8 /** 9 * Created by Administrator on 2015/5/25. 10 */ 11 public class SQLiteHelper extends SQLiteOpenHelper { 12 private Context mcontext; 13 public SQLiteHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) { 14 super(context, name, factory, version); 15 mcontext = context; 16 } 17 @Override 18 public void onCreate(SQLiteDatabase db) { 19 //db.execSQL(CREAT_DB); 20 Toast.makeText(mcontext, "succeed collect!", Toast.LENGTH_SHORT).show(); 21 } 22 23 @Override 24 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 25 } 26 }
写一个空的SQLiteHelper,把表放在后面。
代码里做了详细的注释,类里面传入用户名,返回新建表的String语句。
1 public void CreateNewTable(){ 2 sqLiteHelper = new SQLiteHelper(this,"user_logs.db",null,1); //新建.db文件 3 sqLiteDatabase = sqLiteHelper.getWritableDatabase(); 4 TalkLogs talklog = new TalkLogs(user.UserName_); //获取新建表的语句 5 sqLiteDatabase.execSQL(talklog.returnAString()); //新建表 6 Toast.makeText(friend.this, user.UserName_+" Create success",Toast.LENGTH_SHORT).show(); 7 Log.e(user.UserName_, "success!!!"); 8 //sqLiteDatabase.close(); 9 }
在friend的activity里面,新建该方法,每次进入朋友界面,新建以用户名为名的表,因为用的SQL语句写了if exist 所以已有的不会新建。
1 final ClientConServer server = new ClientConServer(this,mhandler,this.sqLiteDatabase);
对工具类进行实例化,可以解决静态方法不能用在非静态上下文的问题,这里传入context,handler,和数据库,数据库是为了防止打开重复,传入handler是为了桌面Toast
2.修改后的friend活动:
1 package com.lfk.webim; 2 3 import android.content.Intent; 4 import android.database.sqlite.SQLiteDatabase; 5 import android.os.Bundle; 6 import android.os.Handler; 7 import android.support.v4.widget.SwipeRefreshLayout; 8 import android.util.Log; 9 import android.view.Gravity; 10 import android.view.KeyEvent; 11 import android.view.LayoutInflater; 12 import android.view.View; 13 import android.view.ViewGroup; 14 import android.widget.AdapterView; 15 import android.widget.ArrayAdapter; 16 import android.widget.ImageView; 17 import android.widget.ListView; 18 import android.widget.TextView; 19 import android.widget.Toast; 20 21 import com.lfk.webim.appli.BaseActivity; 22 import com.lfk.webim.appli.SQLiteHelper; 23 import com.lfk.webim.appli.TalkLogs; 24 import com.lfk.webim.appli.user; 25 import com.lfk.webim.server.Myserver; 26 import com.lfk.webim.server.connect; 27 28 29 public class friend extends BaseActivity { 30 public static ArrayAdapter<String> mArrayAdapter; 31 public SwipeRefreshLayout swipeLayout; 32 private SQLiteDatabase sqLiteDatabase; 33 private SQLiteHelper sqLiteHelper; 34 @Override 35 protected void onCreate(Bundle savedInstanceState) { 36 super.onCreate(savedInstanceState); 37 setContentView(R.layout.activity_friend); 38 39 CreateNewTable(); 40 final ClientConServer server = new ClientConServer(this,mhandler,this.sqLiteDatabase); 41 42 swipeLayout = (SwipeRefreshLayout)findViewById(R.id.swipe_refresh); 43 TextView textView=(TextView)findViewById(R.id.name); 44 textView.setText(user.UserName_ + "的朋友"); 45 46 Intent intentServer= new Intent(this, Myserver.class); 47 startService(intentServer); 48 49 final ListView listView=(ListView)findViewById(R.id.friend_list); 50 mArrayAdapter= new ArrayAdapter<String>(this, R.layout.list_item); 51 listView.setAdapter(mArrayAdapter); 52 53 //server.getFriends(); 54 //server.getChat(); 55 56 listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { 57 @Override 58 public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, 59 long arg3) { 60 String temp = (String) ((TextView) arg1).getText(); 61 Intent intent = new Intent(); 62 String temper = temp + "@lfkdsk/Smack"; 63 Log.e(temp + "================", temper); 64 user.FromName = temper; 65 user.FromName_ = temp; 66 intent.putExtra("FromName", temper); 67 intent.setClass(friend.this, useractivity.class); 68 startActivity(intent); 69 Toast.makeText(getApplicationContext(), 70 "Chat with " + temp, 71 Toast.LENGTH_SHORT).show(); 72 mArrayAdapter.notifyDataSetChanged(); 73 } 74 }); 75 76 swipeLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { 77 @Override 78 public void onRefresh() { 79 new Handler().postDelayed(new Runnable() {//延迟跳转=-= 80 public void run() { 81 swipeLayout.setRefreshing(true); 82 mArrayAdapter.clear(); 83 server.getFriends(); 84 swipeLayout.setRefreshing(false); 85 } 86 }, 500); 87 } 88 }); 89 } 90 91 public void CreateNewTable(){ 92 sqLiteHelper = new SQLiteHelper(this,"user_logs.db",null,1); //新建.db文件 93 sqLiteDatabase = sqLiteHelper.getWritableDatabase(); 94 TalkLogs talklog = new TalkLogs(user.UserName_); //获取新建表的语句 95 sqLiteDatabase.execSQL(talklog.returnAString()); //新建表 96 Toast.makeText(friend.this, user.UserName_+" Create success",Toast.LENGTH_SHORT).show(); 97 Log.e(user.UserName_, "success!!!"); 98 //sqLiteDatabase.close(); 99 } 100 public Handler mhandler = new Handler() 101 { 102 public void handleMessage(android.os.Message message) 103 { 104 switch (message.what) { 105 case 0: 106 Bundle bundle = (Bundle)message.obj; //桌面Toast的解决方法 107 String s1 = bundle.getString("name"); 108 String s2 = bundle.getString("text"); 109 showCustomToast(s1,s2); 110 break; 111 case 1: { 112 String temp = (String) message.obj; 113 friend.mArrayAdapter.add(temp); 114 break; 115 } 116 } 117 } 118 }; 119 protected void onDestroy() 120 { 121 super.onDestroy(); 122 connect.closeConnection(); 123 Intent stopintent=new Intent(this, Myserver.class); 124 stopService(stopintent); 125 } 126 private long exitTime = 0; 127 @Override 128 public boolean onKeyDown(int keyCode, KeyEvent event) { 129 if(keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN){ 130 Intent home = new Intent(Intent.ACTION_MAIN); 131 home.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 132 home.addCategory(Intent.CATEGORY_HOME); 133 startActivity(home); 134 return true; 135 } 136 return super.onKeyDown(keyCode, event); 137 } 138 public void showCustomToast(String s1, String s2) {//新建显示TOAST 139 // 通用的布局加载器 140 LayoutInflater inflater = getLayoutInflater(); 141 // 加载根容器,方便用于后面的view的定位 142 View layout = inflater.inflate(R.layout.toast_view, (ViewGroup)findViewById(R.id.llToast)); 143 // 设置图片的源文件 144 ImageView image = (ImageView) layout.findViewById(R.id.tvImageToast); 145 image.setImageResource(R.drawable.toast_image); 146 // 设置title及内容 147 TextView title = (TextView) layout.findViewById(R.id.tvTitleToast); 148 title.setText(s1); 149 TextView text = (TextView) layout.findViewById(R.id.tvTextToast); 150 text.setText(s2); 151 Toast tempToast = new Toast(getApplicationContext()); 152 // 设置位置 153 tempToast.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.CENTER, 0, 0); 154 // 设置显示时间 155 tempToast.setDuration(Toast.LENGTH_SHORT); 156 tempToast.setView(layout); 157 tempToast.show(); 158 } 159 }
3.工具类进行了很大的修改,详细讲解:
1 package com.lfk.webim; 2 3 import android.app.ActivityManager; 4 import android.content.ComponentName; 5 import android.content.ContentValues; 6 import android.content.Context; 7 import android.content.Intent; 8 import android.content.pm.PackageManager; 9 import android.content.pm.ResolveInfo; 10 import android.database.Cursor; 11 import android.database.sqlite.SQLiteDatabase; 12 import android.os.Bundle; 13 import android.os.Handler; 14 import android.util.Log; 15 16 import com.lfk.webim.appli.user; 17 import com.lfk.webim.server.connect; 18 19 import org.jivesoftware.smack.Chat; 20 import org.jivesoftware.smack.ChatManager; 21 import org.jivesoftware.smack.ChatManagerListener; 22 import org.jivesoftware.smack.MessageListener; 23 import org.jivesoftware.smack.Roster; 24 import org.jivesoftware.smack.RosterEntry; 25 import org.jivesoftware.smack.RosterGroup; 26 import org.jivesoftware.smack.packet.Message; 27 28 import java.util.ArrayList; 29 import java.util.Collection; 30 import java.util.List; 31 32 33 public class ClientConServer { 34 private Context context; 35 private Handler handlers; 36 private SQLiteDatabase sqLiteDatabase; 37 38 ClientConServer(Context context,Handler handler,SQLiteDatabase sqLiteDatabase){ 39 this.context = context; 40 this.handlers = handler; 41 this.sqLiteDatabase = sqLiteDatabase; 42 getFriends(); 43 getChat(); 44 System.out.print(isAppForground(context)); 45 } 46 //这里收到消息 47 private Handler handler = new Handler(){ 48 public void handleMessage(android.os.Message m) { 49 Message msg = new Message(); 50 msg = (Message) m.obj; 51 //把从服务器获得的消息通过发送 52 String[] message = new String[]{ msg.getFrom(), msg.getBody()}; 53 System.out.println("==========收到消息 From==========="+ message[0]); 54 System.out.println("==========收到消息 Body===========" + message[1]); 55 String s = msg.getFrom(); 56 String s1 = s.split("@")[0]; 57 ContentValues values = new ContentValues(); 58 if(message[1]!=null) { 59 if (user.UserName.equals(message[0])) { 60 values.put("with_id",s1); 61 values.put("talklogs", "ME: " + msg.getBody()); 62 values.put("_ifread",0); 63 Log.e("存入:", "ME: " + msg.getBody()); 64 sqLiteDatabase.insert("\"" + user.UserName_ + "\"", null, values); 65 values.clear(); 66 } else { 67 values.put("with_id", s1); 68 values.put("talklogs", s1 + "说:" + msg.getBody()); 69 values.put("_ifread", 0); 70 Log.e("存入:", s1 + "说:" + msg.getBody()); 71 sqLiteDatabase.insert("\"" + user.UserName_ + "\"", null, values); 72 addUnread(values,s1); 73 } 74 if(isHome(context)){ 75 sendToast(msg,s1); 76 } 77 } 78 } 79 }; 80 public void getFriends(){ 81 //获取用户组、成员信息 82 System.out.println("--------find start----------"); 83 Roster roster = connect.con.getRoster(); 84 Collection<RosterGroup> entriesGroup = roster.getGroups(); 85 System.out.println("team:" + entriesGroup.size()); 86 for(RosterGroup group: entriesGroup){ 87 Collection<RosterEntry> entries = group.getEntries(); 88 int temp=group.getEntryCount(); 89 System.out.println("--------groupnumber--------" + "\n" + temp); 90 System.out.println("--------groupName----------" + "\n" + group.getName()); 91 for (RosterEntry entry : entries) { 92 System.out.println("name:"+entry.getName()); 93 String string2 = entry.getName(); 94 android.os.Message message_list = new android.os.Message(); 95 message_list.obj = string2; 96 message_list.what = 1; 97 handlers.sendMessage(message_list); 98 } 99 } 100 System.out.println("--------find end--------"); 101 } 102 private void addUnread(ContentValues values,String s1){ 103 if (isAppForground(context)&& s1.equals(user.FromName_)) { 104 Cursor cursor = sqLiteDatabase.rawQuery("Select * From "+user.UserName_+" where with_id ="+"\""+user.FromName_+"\""+"And _ifread ="+0,null); 105 if(cursor.moveToFirst()) { 106 do { 107 String talklogs = cursor.getString(cursor.getColumnIndex("talklogs")); 108 useractivity.mConversationArrayAdapter.add(talklogs); 109 Log.e(talklogs, "================"); 110 }while (cursor.moveToNext()); 111 } 112 if(!isAppForground(context)) 113 useractivity.mConversationArrayAdapter.notifyDataSetChanged(); 114 cursor.close(); 115 } 116 values.clear(); 117 } 118 private void sendToast(Message msg,String s1){ 119 android.os.Message message_send = new android.os.Message(); 120 Bundle bundle = new Bundle(); 121 bundle.putString("name",s1); 122 bundle.putString("text",msg.getBody()); 123 message_send.obj = bundle; 124 message_send.what = 0; 125 handlers.sendMessage(message_send); 126 } 127 private void getChat(){ 128 //在登陆以后应该建立一个监听消息的监听器,用来监听收到的消息: 129 ChatManager chatManager = connect.con.getChatManager(); 130 chatManager.addChatListener(new MyChatManagerListener()); 131 } 132 /** message listener*/ 133 class MyChatManagerListener implements ChatManagerListener { 134 public void chatCreated(Chat chat, boolean arg1) { 135 chat.addMessageListener(new MessageListener(){ 136 @Override 137 public void processMessage(Chat chat, Message msg) { 138 android.os.Message m = handler.obtainMessage(); 139 m.obj = msg; 140 m.sendToTarget(); 141 } 142 }); 143 } 144 } 145 public boolean isAppForground(Context mContext) { 146 ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE); 147 List<ActivityManager.RunningTaskInfo> tasks = am.getRunningTasks(1); 148 if (!tasks.isEmpty()) { 149 ComponentName topActivity = tasks.get(0).topActivity; 150 if (!topActivity.getPackageName().equals(mContext.getPackageName())) { 151 return false; 152 } 153 } 154 return true; 155 } 156 public boolean isHome(Context mContext){ 157 ActivityManager mActivityManager = (ActivityManager)mContext.getSystemService(Context.ACTIVITY_SERVICE); 158 List<ActivityManager.RunningTaskInfo> rti = mActivityManager.getRunningTasks(1); 159 return getHomes(mContext).contains(rti.get(0).topActivity.getPackageName()); 160 } 161 /** 162 * 获得属于桌面的应用的应用包名称 163 * @return 返回包含所有包名的字符串列表 164 */ 165 private List<String> getHomes(Context mContext) { 166 List<String> names = new ArrayList<String>(); 167 PackageManager packageManager = mContext.getPackageManager(); 168 //属性 169 Intent intent = new Intent(Intent.ACTION_MAIN); 170 intent.addCategory(Intent.CATEGORY_HOME); 171 List<ResolveInfo> resolveInfo = packageManager.queryIntentActivities(intent, 172 PackageManager.MATCH_DEFAULT_ONLY); 173 for(ResolveInfo ri : resolveInfo){ 174 names.add(ri.activityInfo.packageName); 175 System.out.println(ri.activityInfo.packageName); 176 } 177 return names; 178 } 179 }
1 ClientConServer(Context context,Handler handler,SQLiteDatabase sqLiteDatabase){ 2 this.context = context; 3 this.handlers = handler; 4 this.sqLiteDatabase = sqLiteDatabase; 5 getFriends(); 6 getChat(); 7 System.out.print(isAppForground(context)); 8 }
3.1构造函数,用于实例化。
1 private void addUnread(ContentValues values,String s1){ 2 if (isAppForground(context)&& s1.equals(user.FromName_)) { 3 Cursor cursor = sqLiteDatabase.rawQuery("Select * From "+user.UserName_+" where with_id ="+"\""+user.FromName_+"\""+"And _ifread ="+0,null); 4 if(cursor.moveToFirst()) { 5 do { 6 String talklogs = cursor.getString(cursor.getColumnIndex("talklogs")); 7 useractivity.mConversationArrayAdapter.add(talklogs); 8 Log.e(talklogs, "================"); 9 }while (cursor.moveToNext()); 10 } 11 if(!isAppForground(context)) 12 useractivity.mConversationArrayAdapter.notifyDataSetChanged(); 13 cursor.close(); 14 } 15 values.clear(); 16 }
3.2搜索所有与我聊天的人的记录,并且为未读。
public boolean isAppForground(Context mContext) { ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE); List<ActivityManager.RunningTaskInfo> tasks = am.getRunningTasks(1); if (!tasks.isEmpty()) { ComponentName topActivity = tasks.get(0).topActivity; if (!topActivity.getPackageName().equals(mContext.getPackageName())) { return false; } } return true; } public boolean isHome(Context mContext){ ActivityManager mActivityManager = (ActivityManager)mContext.getSystemService(Context.ACTIVITY_SERVICE); List<ActivityManager.RunningTaskInfo> rti = mActivityManager.getRunningTasks(1); return getHomes(mContext).contains(rti.get(0).topActivity.getPackageName()); } /** * 获得属于桌面的应用的应用包名称 * @return 返回包含所有包名的字符串列表 */ private List<String> getHomes(Context mContext) { List<String> names = new ArrayList<String>(); PackageManager packageManager = mContext.getPackageManager(); //属性 Intent intent = new Intent(Intent.ACTION_MAIN); intent.addCategory(Intent.CATEGORY_HOME); List<ResolveInfo> resolveInfo = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY); for(ResolveInfo ri : resolveInfo){ names.add(ri.activityInfo.packageName); System.out.println(ri.activityInfo.packageName); } return names; } }
3.3判断现在栈顶的活动是什么?还有是否在桌面。
3.4消息的分发机制
这里需要讲解一下我的聊天机制,ChatListener接收数据,然后存入数据库,如果现在的栈顶活动为朋友界面(有一个判断),就默默的存进去,如果是聊天界面就把所有数据库里的取出来,把所有的消息都设为已读(_ifread=1),放在listview里,
然后如果有新消息的话,就用3.1的方法把所有的_ifread的消息取出来,即时的显示在listview里面,如果现在为桌面,就把东西存入然后再Toast出来。
所以handler就是重要的消息分发机制:
1 private Handler handler = new Handler(){ 2 public void handleMessage(android.os.Message m) { 3 Message msg = new Message(); 4 msg = (Message) m.obj; 5 //把从服务器获得的消息通过发送 6 String[] message = new String[]{ msg.getFrom(), msg.getBody()}; 7 System.out.println("==========收到消息 From==========="+ message[0]); 8 System.out.println("==========收到消息 Body===========" + message[1]); 9 String s = msg.getFrom(); 10 String s1 = s.split("@")[0]; 11 ContentValues values = new ContentValues(); 12 if(message[1]!=null) { 13 if (user.UserName.equals(message[0])) { 14 values.put("with_id",s1); 15 values.put("talklogs", "ME: " + msg.getBody()); 16 values.put("_ifread",0); 17 Log.e("存入:", "ME: " + msg.getBody()); 18 sqLiteDatabase.insert("\"" + user.UserName_ + "\"", null, values); 19 values.clear(); 20 } else { 21 values.put("with_id", s1); 22 values.put("talklogs", s1 + "说:" + msg.getBody()); 23 values.put("_ifread", 0); 24 Log.e("存入:", s1 + "说:" + msg.getBody()); 25 sqLiteDatabase.insert("\"" + user.UserName_ + "\"", null, values); 26 addUnread(values,s1); 27 } 28 if(isHome(context)){ 29 sendToast(msg,s1); 30 } 31 } 32 } 33 };
4.改进后的聊天界面:
1 package com.lfk.webim; 2 3 import android.content.ContentValues; 4 import android.database.Cursor; 5 import android.database.sqlite.SQLiteDatabase; 6 import android.os.Bundle; 7 import android.os.Environment; 8 import android.os.Handler; 9 import android.util.Log; 10 import android.view.View; 11 import android.widget.ArrayAdapter; 12 import android.widget.Button; 13 import android.widget.EditText; 14 import android.widget.ListView; 15 import android.widget.TextView; 16 import android.widget.Toast; 17 18 import com.lfk.webim.appli.BaseActivity; 19 import com.lfk.webim.appli.user; 20 import com.lfk.webim.server.connect; 21 22 import org.jivesoftware.smack.Chat; 23 import org.jivesoftware.smack.ChatManager; 24 import org.jivesoftware.smack.MessageListener; 25 import org.jivesoftware.smack.XMPPConnection; 26 import org.jivesoftware.smack.XMPPException; 27 import org.jivesoftware.smack.packet.Message; 28 29 import java.io.File; 30 31 public class useractivity extends BaseActivity { 32 private ListView listView; 33 public static ArrayAdapter<String> mConversationArrayAdapter; 34 private ClientConServer server; 35 private SQLiteDatabase database; 36 @Override 37 protected void onCreate(Bundle savedInstanceState) { 38 super.onCreate(savedInstanceState); 39 setContentView(R.layout.useractivity); 40 41 getActionBar().setDisplayHomeAsUpEnabled(true); 42 43 //server = (ClientConServer)getIntent().getSerializableExtra("ClientConServer"); 44 45 listView = (ListView) findViewById(R.id.in); 46 TextView textView = (TextView) findViewById(R.id.username); 47 textView.setText("Talk with "+user.FromName_); 48 49 mConversationArrayAdapter = new ArrayAdapter<String>(this, R.layout.message); 50 listView.setAdapter(mConversationArrayAdapter); 51 52 OpenDatabase(); 53 54 //server = new ClientConServer(mhandle); 55 56 Button button = (Button)findViewById(R.id.button_send); 57 58 button.setOnClickListener(new View.OnClickListener() { 59 @Override 60 public void onClick(View v) { 61 EditText input = (EditText) findViewById(R.id.edit_text_out); 62 final String content = input.getText().toString(); 63 String string = "ME" + ":" + content; 64 android.os.Message mm = new android.os.Message(); 65 mm.what = 0; 66 mm.obj = content; 67 try { 68 XMPPConnection connection = connect.getConnection(); 69 ChatManager cm = connection.getChatManager(); 70 Chat chat = cm.createChat(user.FromName, new MessageListener() { 71 @Override 72 public void processMessage(Chat chat, Message msg) { 73 msg.setBody(content); 74 Log.i("---", msg.getFrom() + "说:" + msg.getBody()); 75 //添加消息到聊天窗口 76 } 77 }); 78 if (content.equals("")) { 79 mm.what = 1; 80 mhandle.handleMessage(mm); 81 } else { 82 mhandle.handleMessage(mm); 83 chat.sendMessage(content); 84 } 85 input.setText(""); 86 } catch (XMPPException e) { 87 e.printStackTrace(); 88 } 89 } 90 91 }); 92 } 93 public Handler mhandle = new Handler() { 94 public void handleMessage(android.os.Message m) { 95 switch (m.what) { 96 case 1: 97 Toast.makeText(useractivity.this, "不能发送空消息", Toast.LENGTH_SHORT).show(); 98 break; 99 case 0: 100 String respond = (String) m.obj; 101 Log.i("---", respond); 102 ContentValues values = new ContentValues(); 103 values.put("with_id",user.FromName_); 104 values.put("talklogs","ME: "+respond); 105 values.put("_ifread",0); 106 Log.e("存入:", "ME: " + respond); 107 database.insert("\"" + user.UserName_ + "\"", null, values); 108 values.clear(); 109 mConversationArrayAdapter.add("ME: "+respond); 110 mConversationArrayAdapter.notifyDataSetChanged(); 111 break; 112 case 2: 113 //addTheListview(); 114 break; 115 } 116 } 117 }; 118 private void OpenDatabase(){ 119 String DB_NAME = "user_logs.db"; //保存的数据库文件名 120 String PACKAGE_NAME = "com.lfk.webim";// 应用的包名 121 String DB_PATH = "/data" 122 + Environment.getDataDirectory().getAbsolutePath() +"/" 123 + PACKAGE_NAME+ "/databases"; // 在手机里存放数据库的位置 124 File myDataPath = new File(DB_PATH); 125 String dbfile = myDataPath+"/"+DB_NAME; 126 database = SQLiteDatabase.openOrCreateDatabase(dbfile, null); 127 if(!checkColumnExist1(database,user.UserName_,user.FromName_)){ 128 Cursor cursor = database.rawQuery("Select * From "+user.UserName_+" where with_id ="+"\""+user.FromName_+"\"",null); 129 if(cursor.moveToFirst()) { 130 do { 131 String talklogs = cursor.getString(cursor.getColumnIndex("talklogs")); 132 mConversationArrayAdapter.add(talklogs); 133 Log.e(talklogs, "================"); 134 }while (cursor.moveToNext()); 135 } 136 database.execSQL("UPDATE "+user.UserName_+" SET _ifread = 1 "+"Where with_id ="+"\""+user.FromName_+"\""); 137 cursor.close(); 138 //database.close(); 139 } 140 } 141 public static boolean checkColumnExist1(SQLiteDatabase db, String tableName, String columnName) { 142 boolean result = false ; 143 Cursor cursor = null ; 144 try{ 145 //查询一行 146 cursor = db.rawQuery( "SELECT * FROM " + tableName + " LIMIT 0", null ); 147 result = cursor != null && cursor.getColumnIndex(columnName) != -1 ; 148 }catch (Exception e){ 149 Log.e("","checkColumnExists1..." + e.getMessage()) ; 150 }finally{ 151 if(null != cursor && !cursor.isClosed()){ 152 cursor.close() ; 153 } 154 } 155 return result ; 156 } 157 }
1 private void OpenDatabase(){ 2 String DB_NAME = "user_logs.db"; //保存的数据库文件名 3 String PACKAGE_NAME = "com.lfk.webim";// 应用的包名 4 String DB_PATH = "/data" 5 + Environment.getDataDirectory().getAbsolutePath() +"/" 6 + PACKAGE_NAME+ "/databases"; // 在手机里存放数据库的位置 7 File myDataPath = new File(DB_PATH); 8 String dbfile = myDataPath+"/"+DB_NAME; 9 database = SQLiteDatabase.openOrCreateDatabase(dbfile, null); 10 if(!checkColumnExist1(database,user.UserName_,user.FromName_)){ 11 Cursor cursor = database.rawQuery("Select * From "+user.UserName_+" where with_id ="+"\""+user.FromName_+"\"",null); 12 if(cursor.moveToFirst()) { 13 do { 14 String talklogs = cursor.getString(cursor.getColumnIndex("talklogs")); 15 mConversationArrayAdapter.add(talklogs); 16 Log.e(talklogs, "================"); 17 }while (cursor.moveToNext()); 18 } 19 database.execSQL("UPDATE "+user.UserName_+" SET _ifread = 1 "+"Where with_id ="+"\""+user.FromName_+"\""); 20 cursor.close(); 21 //database.close(); 22 } 23 }
每次进入都先打开数据库,并且把所有的聊天对应的人的数据库信息取出来,然后把所有的已读标志设为1;
1 public static boolean checkColumnExist1(SQLiteDatabase db, String tableName, String columnName) { 2 boolean result = false ; 3 Cursor cursor = null ; 4 try{ 5 //查询一行 6 cursor = db.rawQuery( "SELECT * FROM " + tableName + " LIMIT 0", null ); 7 result = cursor != null && cursor.getColumnIndex(columnName) != -1 ; 8 }catch (Exception e){ 9 Log.e("","checkColumnExists1..." + e.getMessage()) ; 10 }finally{ 11 if(null != cursor && !cursor.isClosed()){ 12 cursor.close() ; 13 } 14 } 15 return result ; 16 }
这里用到了一个方法,用来判断表里有没有你的这个字段,如果没有就不用添加到listview里,否则你没和他聊过会崩!!
1 public Handler mhandle = new Handler() { 2 public void handleMessage(android.os.Message m) { 3 switch (m.what) { 4 case 1: 5 Toast.makeText(useractivity.this, "不能发送空消息", Toast.LENGTH_SHORT).show(); 6 break; 7 case 0: 8 String respond = (String) m.obj; 9 Log.i("---", respond); 10 ContentValues values = new ContentValues(); 11 values.put("with_id",user.FromName_); 12 values.put("talklogs","ME: "+respond); 13 values.put("_ifread",0); 14 Log.e("存入:", "ME: " + respond); 15 database.insert("\"" + user.UserName_ + "\"", null, values); 16 values.clear(); 17 mConversationArrayAdapter.add("ME: "+respond); 18 mConversationArrayAdapter.notifyDataSetChanged(); 19 break; 20 case 2: 21 //addTheListview(); 22 break; 23 } 24 } 25 };
在自己发送消息的时候,存入数据库,然后添加到listview里面。
3.桌面显示的Toast:
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:id="@+id/llToast" 4 android:layout_width="wrap_content" 5 android:layout_height="wrap_content" 6 android:background="#ffffffff" 7 android:orientation="vertical" > 8 9 <TextView 10 android:id="@+id/tvTitleToast" 11 android:layout_width="match_parent" 12 android:layout_height="wrap_content" 13 android:layout_margin="1dip" 14 android:background="#bb000000" 15 android:gravity="center" 16 android:text="Title" 17 android:textColor="#ffffffff" /> 18 19 <LinearLayout 20 android:id="@+id/llToastContent" 21 android:layout_width="wrap_content" 22 android:layout_height="wrap_content" 23 android:layout_marginBottom="1dip" 24 android:layout_marginLeft="1dip" 25 android:layout_marginRight="1dip" 26 android:background="#44000000" 27 android:orientation="vertical" 28 android:padding="15dip" > 29 30 <ImageView 31 android:id="@+id/tvImageToast" 32 android:layout_width="wrap_content" 33 android:layout_height="wrap_content" 34 android:layout_gravity="center" 35 android:contentDescription="@string/hello_world" 36 android:src="@drawable/toast_image" /> 37 38 <TextView 39 android:id="@+id/tvTextToast" 40 android:layout_width="128dp" 41 android:layout_height="wrap_content" 42 android:gravity="center" 43 android:paddingLeft="10dip" 44 android:paddingRight="10dip" 45 android:singleLine="false" 46 android:text="自定义显示语句" 47 android:textColor="#ff000000" /> 48 </LinearLayout> 49 50 </LinearLayout>
1.添加一个toast的布局文件,写出来的样子是这样的:
2.friend里面添加一个方法进行处理:
1 public void showCustomToast(String s1, String s2) {//新建显示TOAST 2 // 通用的布局加载器 3 LayoutInflater inflater = getLayoutInflater(); 4 // 加载根容器,方便用于后面的view的定位 5 View layout = inflater.inflate(R.layout.toast_view, (ViewGroup)findViewById(R.id.llToast)); 6 // 设置图片的源文件 7 ImageView image = (ImageView) layout.findViewById(R.id.tvImageToast); 8 image.setImageResource(R.drawable.toast_image); 9 // 设置title及内容 10 TextView title = (TextView) layout.findViewById(R.id.tvTitleToast); 11 title.setText(s1); 12 TextView text = (TextView) layout.findViewById(R.id.tvTextToast); 13 text.setText(s2); 14 Toast tempToast = new Toast(getApplicationContext()); 15 // 设置位置 16 tempToast.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.CENTER, 0, 0); 17 // 设置显示时间 18 tempToast.setDuration(Toast.LENGTH_SHORT); 19 tempToast.setView(layout); 20 tempToast.show(); 21 } 22 }
3.显示:
刚才在friend里面我们对工具类进行了实例化,传入了handler,就是要在工具类用handler回调,用friend的handler进行处理:
1 if(isHome(context)){ 2 sendToast(msg,s1); 3 }
如果在桌面:
1 private void sendToast(Message msg,String s1){ 2 android.os.Message message_send = new android.os.Message(); 3 Bundle bundle = new Bundle(); 4 bundle.putString("name",s1); 5 bundle.putString("text",msg.getBody()); 6 message_send.obj = bundle; 7 message_send.what = 0; 8 handlers.sendMessage(message_send); 9 }
打包名字,信息发到friend的handler里去。
1 public Handler mhandler = new Handler() 2 { 3 public void handleMessage(android.os.Message message) 4 { 5 switch (message.what) { 6 case 0: 7 Bundle bundle = (Bundle)message.obj; //桌面Toast的解决方法 8 String s1 = bundle.getString("name"); 9 String s2 = bundle.getString("text"); 10 showCustomToast(s1,s2); 11 break; 12 case 1: { 13 String temp = (String) message.obj; 14 friend.mArrayAdapter.add(temp); 15 break; 16 } 17 } 18 } 19 };
friend的Handler里处理一下,就能显示出来了。
这一次就说这么多吧,整个Demo已经能像正常的IM应用一样使用了,还有一些自己的修改方法,在下一篇的后续里会增加加好友啊,
加组,转入server里的一系列方法,敬请期待!
喜欢就点赞吧!!!