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库吧,省的大家用的不一样:http://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开始:
<TableRow>
<TextView
android:textColor="#ffc2c6c6"
android:layout_height="wrap_content"
android:text="Ip"/>
<EditText
android:id="@+id/login_ip"
android:hint="Input your Ip"
android:maxLines="1"
android:layout_height="wrap_content"
/>
</TableRow>
先在TableLayout里添加。
静态数据类里添加:
//ip名称
public static String My_Ip = "";
主活动的添加:
ip = (EditText) findViewById(R.id.login_ip);
check_init()函数里添加:
private void checkbox_init() {//checkbox判断函数
//判断记住密码多选框的状态
if(sp.getBoolean("ISCHECK", false))
{
//设置默认是记录密码状态
check_save.setChecked(true);
ip.setText(sp.getString("USER_IP", ""));
name.setText(sp.getString("USER_NAME",""));
password.setText(sp.getString("PASSWORD",""));
//判断自动登陆多选框状态
if(sp.getBoolean("AUTO_ISCHECK", false))
{
//设置默认是自动登录状态
check_auto.setChecked(true);
//跳转界面
//account=sp.getString("USER_NAME","");
//pwd=sp.getString("PASSWORD","");
Log.i("======================"+account,pwd+"===================================");
accountLogin();
}
}
}
private void setCheck_save(){
if(check_save.isChecked())
{
//记住用户名、密码、
editor = sp.edit();
editor.putString("USER_IP", user.My_Ip);
editor.putString("USER_NAME", account);
editor.putString("PASSWORD",pwd);
editor.apply();
}
}
这个是把Ip添加进记录。
修改登录的方法:
private void accountLogin() {
new Thread() {
public void run() {
user.My_Ip = ((EditText)findViewById(R.id.login_ip))
.getText().toString();
account = ((EditText) findViewById(R.id.login_name))
.getText().toString();
pwd = ((EditText) findViewById(R.id.login_password)).getText()
.toString();
boolean is = ConnecMethod.login(account, pwd);
if (is) {
insHandler.sendEmptyMessage(1);
// 将用户名保存
user.UserName = account+"@lfkdsk/Spark 2.6.3";
user.UserName_= account;
setCheck_save();
} else {
insHandler.sendEmptyMessage(0);
}
}
}.start();
}
但是要是逐层的为函数添加参数,然后无限的传参也是一种不太现实的方法,所以我们在XMpp连接的地方直接调用静态存储的IP:
public static boolean openConnection() {
try {
connConfig = new ConnectionConfiguration(user.My_Ip, 5222);
// 设置登录状态为离线
connConfig.setSendPresence(false);
// 断网重连
connConfig.setReconnectionAllowed(true);
con = new XMPPConnection(connConfig);
con.connect();
return true;
} catch (Exception e) { }
return false;
}
这样我们登陆的时候就能手动指定ip或者是域名了,增强了通用性。
2.本地化数据的具体操作:
1.新建一个类作为本地数据库的模版:
package com.lfk.webim.appli; import android.util.Log; /**
* Created by Administrator on 2015/5/26.
*/
public class TalkLogs {
private String ID = "_id"; //数据库主键,自增
private String With_Id ="with_id"; //和谁聊天
private String Logs = "talklogs"; //聊天记录
private String If_read = "_ifread"; //是否已读
private String dbname; //数据表名---为用户名,即user.UserName_
private String CREAT_DB = ""; //数据库新建的语句 public TalkLogs(String dbname){
this.dbname = dbname;
giveanameto(dbname);
Log.e("dbname=====", this.dbname);
Log.e("dbname参数=====",dbname);
}
private void giveanameto(String dbname){
CREAT_DB = "CREATE TABLE if not exists "+dbname+"("
+this.ID +" integer primary key autoincrement,"
+this.With_Id+","
+this.If_read+" integer,"
+ this.Logs+")";
}
public String returnAString(){
Log.e("CREAT_DB===========",CREAT_DB);
return CREAT_DB;
}
}
package com.lfk.webim.appli; import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.widget.Toast; /**
* Created by Administrator on 2015/5/25.
*/
public class SQLiteHelper extends SQLiteOpenHelper {
private Context mcontext;
public SQLiteHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
mcontext = context;
}
@Override
public void onCreate(SQLiteDatabase db) {
//db.execSQL(CREAT_DB);
Toast.makeText(mcontext, "succeed collect!", Toast.LENGTH_SHORT).show();
} @Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
写一个空的SQLiteHelper,把表放在后面。
代码里做了详细的注释,类里面传入用户名,返回新建表的String语句。
public void CreateNewTable(){
sqLiteHelper = new SQLiteHelper(this,"user_logs.db",null,1); //新建.db文件
sqLiteDatabase = sqLiteHelper.getWritableDatabase();
TalkLogs talklog = new TalkLogs(user.UserName_); //获取新建表的语句
sqLiteDatabase.execSQL(talklog.returnAString()); //新建表
Toast.makeText(friend.this, user.UserName_+" Create success",Toast.LENGTH_SHORT).show();
Log.e(user.UserName_, "success!!!");
//sqLiteDatabase.close();
}
在friend的activity里面,新建该方法,每次进入朋友界面,新建以用户名为名的表,因为用的SQL语句写了if exist 所以已有的不会新建。
final ClientConServer server = new ClientConServer(this,mhandler,this.sqLiteDatabase);
对工具类进行实例化,可以解决静态方法不能用在非静态上下文的问题,这里传入context,handler,和数据库,数据库是为了防止打开重复,传入handler是为了桌面Toast
2.修改后的friend活动:
package com.lfk.webim; import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.widget.SwipeRefreshLayout;
import android.util.Log;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast; import com.lfk.webim.appli.BaseActivity;
import com.lfk.webim.appli.SQLiteHelper;
import com.lfk.webim.appli.TalkLogs;
import com.lfk.webim.appli.user;
import com.lfk.webim.server.Myserver;
import com.lfk.webim.server.connect; public class friend extends BaseActivity {
public static ArrayAdapter<String> mArrayAdapter;
public SwipeRefreshLayout swipeLayout;
private SQLiteDatabase sqLiteDatabase;
private SQLiteHelper sqLiteHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_friend); CreateNewTable();
final ClientConServer server = new ClientConServer(this,mhandler,this.sqLiteDatabase); swipeLayout = (SwipeRefreshLayout)findViewById(R.id.swipe_refresh);
TextView textView=(TextView)findViewById(R.id.name);
textView.setText(user.UserName_ + "的朋友"); Intent intentServer= new Intent(this, Myserver.class);
startService(intentServer); final ListView listView=(ListView)findViewById(R.id.friend_list);
mArrayAdapter= new ArrayAdapter<String>(this, R.layout.list_item);
listView.setAdapter(mArrayAdapter); //server.getFriends();
//server.getChat(); listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
String temp = (String) ((TextView) arg1).getText();
Intent intent = new Intent();
String temper = temp + "@lfkdsk/Smack";
Log.e(temp + "================", temper);
user.FromName = temper;
user.FromName_ = temp;
intent.putExtra("FromName", temper);
intent.setClass(friend.this, useractivity.class);
startActivity(intent);
Toast.makeText(getApplicationContext(),
"Chat with " + temp,
Toast.LENGTH_SHORT).show();
mArrayAdapter.notifyDataSetChanged();
}
}); swipeLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
new Handler().postDelayed(new Runnable() {//延迟跳转=-=
public void run() {
swipeLayout.setRefreshing(true);
mArrayAdapter.clear();
server.getFriends();
swipeLayout.setRefreshing(false);
}
}, 500);
}
});
} public void CreateNewTable(){
sqLiteHelper = new SQLiteHelper(this,"user_logs.db",null,1); //新建.db文件
sqLiteDatabase = sqLiteHelper.getWritableDatabase();
TalkLogs talklog = new TalkLogs(user.UserName_); //获取新建表的语句
sqLiteDatabase.execSQL(talklog.returnAString()); //新建表
Toast.makeText(friend.this, user.UserName_+" Create success",Toast.LENGTH_SHORT).show();
Log.e(user.UserName_, "success!!!");
//sqLiteDatabase.close();
}
public Handler mhandler = new Handler()
{
public void handleMessage(android.os.Message message)
{
switch (message.what) {
case 0:
Bundle bundle = (Bundle)message.obj; //桌面Toast的解决方法
String s1 = bundle.getString("name");
String s2 = bundle.getString("text");
showCustomToast(s1,s2);
break;
case 1: {
String temp = (String) message.obj;
friend.mArrayAdapter.add(temp);
break;
}
}
}
};
protected void onDestroy()
{
super.onDestroy();
connect.closeConnection();
Intent stopintent=new Intent(this, Myserver.class);
stopService(stopintent);
}
private long exitTime = 0;
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if(keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN){
Intent home = new Intent(Intent.ACTION_MAIN);
home.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
home.addCategory(Intent.CATEGORY_HOME);
startActivity(home);
return true;
}
return super.onKeyDown(keyCode, event);
}
public void showCustomToast(String s1, String s2) {//新建显示TOAST
// 通用的布局加载器
LayoutInflater inflater = getLayoutInflater();
// 加载根容器,方便用于后面的view的定位
View layout = inflater.inflate(R.layout.toast_view, (ViewGroup)findViewById(R.id.llToast));
// 设置图片的源文件
ImageView image = (ImageView) layout.findViewById(R.id.tvImageToast);
image.setImageResource(R.drawable.toast_image);
// 设置title及内容
TextView title = (TextView) layout.findViewById(R.id.tvTitleToast);
title.setText(s1);
TextView text = (TextView) layout.findViewById(R.id.tvTextToast);
text.setText(s2);
Toast tempToast = new Toast(getApplicationContext());
// 设置位置
tempToast.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.CENTER, 0, 0);
// 设置显示时间
tempToast.setDuration(Toast.LENGTH_SHORT);
tempToast.setView(layout);
tempToast.show();
}
}
friend活动
3.工具类进行了很大的修改,详细讲解:
package com.lfk.webim; import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log; import com.lfk.webim.appli.user;
import com.lfk.webim.server.connect; import org.jivesoftware.smack.Chat;
import org.jivesoftware.smack.ChatManager;
import org.jivesoftware.smack.ChatManagerListener;
import org.jivesoftware.smack.MessageListener;
import org.jivesoftware.smack.Roster;
import org.jivesoftware.smack.RosterEntry;
import org.jivesoftware.smack.RosterGroup;
import org.jivesoftware.smack.packet.Message; import java.util.ArrayList;
import java.util.Collection;
import java.util.List; public class ClientConServer {
private Context context;
private Handler handlers;
private SQLiteDatabase sqLiteDatabase; ClientConServer(Context context,Handler handler,SQLiteDatabase sqLiteDatabase){
this.context = context;
this.handlers = handler;
this.sqLiteDatabase = sqLiteDatabase;
getFriends();
getChat();
System.out.print(isAppForground(context));
}
//这里收到消息
private Handler handler = new Handler(){
public void handleMessage(android.os.Message m) {
Message msg = new Message();
msg = (Message) m.obj;
//把从服务器获得的消息通过发送
String[] message = new String[]{ msg.getFrom(), msg.getBody()};
System.out.println("==========收到消息 From==========="+ message[0]);
System.out.println("==========收到消息 Body===========" + message[1]);
String s = msg.getFrom();
String s1 = s.split("@")[0];
ContentValues values = new ContentValues();
if(message[1]!=null) {
if (user.UserName.equals(message[0])) {
values.put("with_id",s1);
values.put("talklogs", "ME: " + msg.getBody());
values.put("_ifread",0);
Log.e("存入:", "ME: " + msg.getBody());
sqLiteDatabase.insert("\"" + user.UserName_ + "\"", null, values);
values.clear();
} else {
values.put("with_id", s1);
values.put("talklogs", s1 + "说:" + msg.getBody());
values.put("_ifread", 0);
Log.e("存入:", s1 + "说:" + msg.getBody());
sqLiteDatabase.insert("\"" + user.UserName_ + "\"", null, values);
addUnread(values,s1);
}
if(isHome(context)){
sendToast(msg,s1);
}
}
}
};
public void getFriends(){
//获取用户组、成员信息
System.out.println("--------find start----------");
Roster roster = connect.con.getRoster();
Collection<RosterGroup> entriesGroup = roster.getGroups();
System.out.println("team:" + entriesGroup.size());
for(RosterGroup group: entriesGroup){
Collection<RosterEntry> entries = group.getEntries();
int temp=group.getEntryCount();
System.out.println("--------groupnumber--------" + "\n" + temp);
System.out.println("--------groupName----------" + "\n" + group.getName());
for (RosterEntry entry : entries) {
System.out.println("name:"+entry.getName());
String string2 = entry.getName();
android.os.Message message_list = new android.os.Message();
message_list.obj = string2;
message_list.what = 1;
handlers.sendMessage(message_list);
}
}
System.out.println("--------find end--------");
}
private void addUnread(ContentValues values,String s1){
if (isAppForground(context)&& s1.equals(user.FromName_)) {
Cursor cursor = sqLiteDatabase.rawQuery("Select * From "+user.UserName_+" where with_id ="+"\""+user.FromName_+"\""+"And _ifread ="+0,null);
if(cursor.moveToFirst()) {
do {
String talklogs = cursor.getString(cursor.getColumnIndex("talklogs"));
useractivity.mConversationArrayAdapter.add(talklogs);
Log.e(talklogs, "================");
}while (cursor.moveToNext());
}
if(!isAppForground(context))
useractivity.mConversationArrayAdapter.notifyDataSetChanged();
cursor.close();
}
values.clear();
}
private void sendToast(Message msg,String s1){
android.os.Message message_send = new android.os.Message();
Bundle bundle = new Bundle();
bundle.putString("name",s1);
bundle.putString("text",msg.getBody());
message_send.obj = bundle;
message_send.what = 0;
handlers.sendMessage(message_send);
}
private void getChat(){
//在登陆以后应该建立一个监听消息的监听器,用来监听收到的消息:
ChatManager chatManager = connect.con.getChatManager();
chatManager.addChatListener(new MyChatManagerListener());
}
/** message listener*/
class MyChatManagerListener implements ChatManagerListener {
public void chatCreated(Chat chat, boolean arg1) {
chat.addMessageListener(new MessageListener(){
@Override
public void processMessage(Chat chat, Message msg) {
android.os.Message m = handler.obtainMessage();
m.obj = msg;
m.sendToTarget();
}
});
}
}
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;
}
}
工具类
ClientConServer(Context context,Handler handler,SQLiteDatabase sqLiteDatabase){
this.context = context;
this.handlers = handler;
this.sqLiteDatabase = sqLiteDatabase;
getFriends();
getChat();
System.out.print(isAppForground(context));
}
3.1构造函数,用于实例化。
private void addUnread(ContentValues values,String s1){
if (isAppForground(context)&& s1.equals(user.FromName_)) {
Cursor cursor = sqLiteDatabase.rawQuery("Select * From "+user.UserName_+" where with_id ="+"\""+user.FromName_+"\""+"And _ifread ="+0,null);
if(cursor.moveToFirst()) {
do {
String talklogs = cursor.getString(cursor.getColumnIndex("talklogs"));
useractivity.mConversationArrayAdapter.add(talklogs);
Log.e(talklogs, "================");
}while (cursor.moveToNext());
}
if(!isAppForground(context))
useractivity.mConversationArrayAdapter.notifyDataSetChanged();
cursor.close();
}
values.clear();
}
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就是重要的消息分发机制:
private Handler handler = new Handler(){
public void handleMessage(android.os.Message m) {
Message msg = new Message();
msg = (Message) m.obj;
//把从服务器获得的消息通过发送
String[] message = new String[]{ msg.getFrom(), msg.getBody()};
System.out.println("==========收到消息 From==========="+ message[0]);
System.out.println("==========收到消息 Body===========" + message[1]);
String s = msg.getFrom();
String s1 = s.split("@")[0];
ContentValues values = new ContentValues();
if(message[1]!=null) {
if (user.UserName.equals(message[0])) {
values.put("with_id",s1);
values.put("talklogs", "ME: " + msg.getBody());
values.put("_ifread",0);
Log.e("存入:", "ME: " + msg.getBody());
sqLiteDatabase.insert("\"" + user.UserName_ + "\"", null, values);
values.clear();
} else {
values.put("with_id", s1);
values.put("talklogs", s1 + "说:" + msg.getBody());
values.put("_ifread", 0);
Log.e("存入:", s1 + "说:" + msg.getBody());
sqLiteDatabase.insert("\"" + user.UserName_ + "\"", null, values);
addUnread(values,s1);
}
if(isHome(context)){
sendToast(msg,s1);
}
}
}
};
4.改进后的聊天界面:
package com.lfk.webim; import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast; import com.lfk.webim.appli.BaseActivity;
import com.lfk.webim.appli.user;
import com.lfk.webim.server.connect; import org.jivesoftware.smack.Chat;
import org.jivesoftware.smack.ChatManager;
import org.jivesoftware.smack.MessageListener;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Message; import java.io.File; public class useractivity extends BaseActivity {
private ListView listView;
public static ArrayAdapter<String> mConversationArrayAdapter;
private ClientConServer server;
private SQLiteDatabase database;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.useractivity); getActionBar().setDisplayHomeAsUpEnabled(true); //server = (ClientConServer)getIntent().getSerializableExtra("ClientConServer"); listView = (ListView) findViewById(R.id.in);
TextView textView = (TextView) findViewById(R.id.username);
textView.setText("Talk with "+user.FromName_); mConversationArrayAdapter = new ArrayAdapter<String>(this, R.layout.message);
listView.setAdapter(mConversationArrayAdapter); OpenDatabase(); //server = new ClientConServer(mhandle); Button button = (Button)findViewById(R.id.button_send); button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
EditText input = (EditText) findViewById(R.id.edit_text_out);
final String content = input.getText().toString();
String string = "ME" + ":" + content;
android.os.Message mm = new android.os.Message();
mm.what = 0;
mm.obj = content;
try {
XMPPConnection connection = connect.getConnection();
ChatManager cm = connection.getChatManager();
Chat chat = cm.createChat(user.FromName, new MessageListener() {
@Override
public void processMessage(Chat chat, Message msg) {
msg.setBody(content);
Log.i("---", msg.getFrom() + "说:" + msg.getBody());
//添加消息到聊天窗口
}
});
if (content.equals("")) {
mm.what = 1;
mhandle.handleMessage(mm);
} else {
mhandle.handleMessage(mm);
chat.sendMessage(content);
}
input.setText("");
} catch (XMPPException e) {
e.printStackTrace();
}
} });
}
public Handler mhandle = new Handler() {
public void handleMessage(android.os.Message m) {
switch (m.what) {
case 1:
Toast.makeText(useractivity.this, "不能发送空消息", Toast.LENGTH_SHORT).show();
break;
case 0:
String respond = (String) m.obj;
Log.i("---", respond);
ContentValues values = new ContentValues();
values.put("with_id",user.FromName_);
values.put("talklogs","ME: "+respond);
values.put("_ifread",0);
Log.e("存入:", "ME: " + respond);
database.insert("\"" + user.UserName_ + "\"", null, values);
values.clear();
mConversationArrayAdapter.add("ME: "+respond);
mConversationArrayAdapter.notifyDataSetChanged();
break;
case 2:
//addTheListview();
break;
}
}
};
private void OpenDatabase(){
String DB_NAME = "user_logs.db"; //保存的数据库文件名
String PACKAGE_NAME = "com.lfk.webim";// 应用的包名
String DB_PATH = "/data"
+ Environment.getDataDirectory().getAbsolutePath() +"/"
+ PACKAGE_NAME+ "/databases"; // 在手机里存放数据库的位置
File myDataPath = new File(DB_PATH);
String dbfile = myDataPath+"/"+DB_NAME;
database = SQLiteDatabase.openOrCreateDatabase(dbfile, null);
if(!checkColumnExist1(database,user.UserName_,user.FromName_)){
Cursor cursor = database.rawQuery("Select * From "+user.UserName_+" where with_id ="+"\""+user.FromName_+"\"",null);
if(cursor.moveToFirst()) {
do {
String talklogs = cursor.getString(cursor.getColumnIndex("talklogs"));
mConversationArrayAdapter.add(talklogs);
Log.e(talklogs, "================");
}while (cursor.moveToNext());
}
database.execSQL("UPDATE "+user.UserName_+" SET _ifread = 1 "+"Where with_id ="+"\""+user.FromName_+"\"");
cursor.close();
//database.close();
}
}
public static boolean checkColumnExist1(SQLiteDatabase db, String tableName, String columnName) {
boolean result = false ;
Cursor cursor = null ;
try{
//查询一行
cursor = db.rawQuery( "SELECT * FROM " + tableName + " LIMIT 0", null );
result = cursor != null && cursor.getColumnIndex(columnName) != -1 ;
}catch (Exception e){
Log.e("","checkColumnExists1..." + e.getMessage()) ;
}finally{
if(null != cursor && !cursor.isClosed()){
cursor.close() ;
}
}
return result ;
}
}
聊天活动
private void OpenDatabase(){
String DB_NAME = "user_logs.db"; //保存的数据库文件名
String PACKAGE_NAME = "com.lfk.webim";// 应用的包名
String DB_PATH = "/data"
+ Environment.getDataDirectory().getAbsolutePath() +"/"
+ PACKAGE_NAME+ "/databases"; // 在手机里存放数据库的位置
File myDataPath = new File(DB_PATH);
String dbfile = myDataPath+"/"+DB_NAME;
database = SQLiteDatabase.openOrCreateDatabase(dbfile, null);
if(!checkColumnExist1(database,user.UserName_,user.FromName_)){
Cursor cursor = database.rawQuery("Select * From "+user.UserName_+" where with_id ="+"\""+user.FromName_+"\"",null);
if(cursor.moveToFirst()) {
do {
String talklogs = cursor.getString(cursor.getColumnIndex("talklogs"));
mConversationArrayAdapter.add(talklogs);
Log.e(talklogs, "================");
}while (cursor.moveToNext());
}
database.execSQL("UPDATE "+user.UserName_+" SET _ifread = 1 "+"Where with_id ="+"\""+user.FromName_+"\"");
cursor.close();
//database.close();
}
}
每次进入都先打开数据库,并且把所有的聊天对应的人的数据库信息取出来,然后把所有的已读标志设为1;
public static boolean checkColumnExist1(SQLiteDatabase db, String tableName, String columnName) {
boolean result = false ;
Cursor cursor = null ;
try{
//查询一行
cursor = db.rawQuery( "SELECT * FROM " + tableName + " LIMIT 0", null );
result = cursor != null && cursor.getColumnIndex(columnName) != -1 ;
}catch (Exception e){
Log.e("","checkColumnExists1..." + e.getMessage()) ;
}finally{
if(null != cursor && !cursor.isClosed()){
cursor.close() ;
}
}
return result ;
}
这里用到了一个方法,用来判断表里有没有你的这个字段,如果没有就不用添加到listview里,否则你没和他聊过会崩!!
public Handler mhandle = new Handler() {
public void handleMessage(android.os.Message m) {
switch (m.what) {
case 1:
Toast.makeText(useractivity.this, "不能发送空消息", Toast.LENGTH_SHORT).show();
break;
case 0:
String respond = (String) m.obj;
Log.i("---", respond);
ContentValues values = new ContentValues();
values.put("with_id",user.FromName_);
values.put("talklogs","ME: "+respond);
values.put("_ifread",0);
Log.e("存入:", "ME: " + respond);
database.insert("\"" + user.UserName_ + "\"", null, values);
values.clear();
mConversationArrayAdapter.add("ME: "+respond);
mConversationArrayAdapter.notifyDataSetChanged();
break;
case 2:
//addTheListview();
break;
}
}
};
在自己发送消息的时候,存入数据库,然后添加到listview里面。
3.桌面显示的Toast:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/llToast"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#ffffffff"
android:orientation="vertical" > <TextView
android:id="@+id/tvTitleToast"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="1dip"
android:background="#bb000000"
android:gravity="center"
android:text="Title"
android:textColor="#ffffffff" /> <LinearLayout
android:id="@+id/llToastContent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="1dip"
android:layout_marginLeft="1dip"
android:layout_marginRight="1dip"
android:background="#44000000"
android:orientation="vertical"
android:padding="15dip" > <ImageView
android:id="@+id/tvImageToast"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:contentDescription="@string/hello_world"
android:src="@drawable/toast_image" /> <TextView
android:id="@+id/tvTextToast"
android:layout_width="128dp"
android:layout_height="wrap_content"
android:gravity="center"
android:paddingLeft="10dip"
android:paddingRight="10dip"
android:singleLine="false"
android:text="自定义显示语句"
android:textColor="#ff000000" />
</LinearLayout> </LinearLayout>
1.添加一个toast的布局文件,写出来的样子是这样的:
2.friend里面添加一个方法进行处理:
public void showCustomToast(String s1, String s2) {//新建显示TOAST
// 通用的布局加载器
LayoutInflater inflater = getLayoutInflater();
// 加载根容器,方便用于后面的view的定位
View layout = inflater.inflate(R.layout.toast_view, (ViewGroup)findViewById(R.id.llToast));
// 设置图片的源文件
ImageView image = (ImageView) layout.findViewById(R.id.tvImageToast);
image.setImageResource(R.drawable.toast_image);
// 设置title及内容
TextView title = (TextView) layout.findViewById(R.id.tvTitleToast);
title.setText(s1);
TextView text = (TextView) layout.findViewById(R.id.tvTextToast);
text.setText(s2);
Toast tempToast = new Toast(getApplicationContext());
// 设置位置
tempToast.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.CENTER, 0, 0);
// 设置显示时间
tempToast.setDuration(Toast.LENGTH_SHORT);
tempToast.setView(layout);
tempToast.show();
}
}
3.显示:
刚才在friend里面我们对工具类进行了实例化,传入了handler,就是要在工具类用handler回调,用friend的handler进行处理:
if(isHome(context)){
sendToast(msg,s1);
}
如果在桌面:
private void sendToast(Message msg,String s1){
android.os.Message message_send = new android.os.Message();
Bundle bundle = new Bundle();
bundle.putString("name",s1);
bundle.putString("text",msg.getBody());
message_send.obj = bundle;
message_send.what = 0;
handlers.sendMessage(message_send);
}
打包名字,信息发到friend的handler里去。
public Handler mhandler = new Handler()
{
public void handleMessage(android.os.Message message)
{
switch (message.what) {
case 0:
Bundle bundle = (Bundle)message.obj; //桌面Toast的解决方法
String s1 = bundle.getString("name");
String s2 = bundle.getString("text");
showCustomToast(s1,s2);
break;
case 1: {
String temp = (String) message.obj;
friend.mArrayAdapter.add(temp);
break;
}
}
}
};
friend的Handler里处理一下,就能显示出来了。
这一次就说这么多吧,整个Demo已经能像正常的IM应用一样使用了,还有一些自己的修改方法,在下一篇的后续里会增加加好友啊,
加组,转入server里的一系列方法,敬请期待!
喜欢就点赞吧!!!
openfire+asmack搭建的安卓即时通讯(七) 15.5.27的更多相关文章
- openfire+asmack搭建的安卓即时通讯(一) 15.4.7
最进开始做一些android的项目,除了一个新闻客户端的搭建,还需要一个实现一个即时通讯的功能,参考了很多大神成型的实例,了解到operfire+asmack是搭建简易即时通讯比较方便,所以就写了这篇 ...
- openfire+asmack搭建的安卓即时通讯(三) 15.4.9
(能用得上话的话求点赞=-=,我表达不好的话跟我说哦) 上一次我们拿到了服务器端的组数据和用户信息,这就可以为我们日后使用好友系统打下基础了! 但是光是拿到了这些东西我们怎么能够满足呢?我们一个即时通 ...
- openfire+asmack搭建的安卓即时通讯(四) 15.4.10
之前的教程不知道你们成功了没,,,没成功可以问我啊=-= 第四篇博文是要实现发送消息的功能. 首先在我们登陆后的活动的layout里添加这样的两个控件,一个EditText和一个Button用于发送数 ...
- openfire+asmack搭建的安卓即时通讯(六) 15.4.16
啊啊啊啊啊啊啊啊,这东西越做越觉得是个深坑啊! 1.SharedPreferences.Editor的密码保存和自动登录: 首先还是从主界面开始,因为要提升一下用户体验自然要加入保存密码和自动登录的功 ...
- openfire+asmack搭建的安卓即时通讯(五) 15.4.12
这一篇博客其实是要昨天写的,但昨天做了作修改就停不下来了,这次的修改应该是前期开发的最终回了,其余的功能有空再做了,下周可能要做一些好玩的东西,敬请期待! 1.修改下Logo:(Just We) ht ...
- openfire+asmack搭建的安卓即时通讯(二) 15.4.9
上期没有放成果图呢!忘了=-=,这就是上次的成果图,textview里面会显示登陆的名字(这个是默认管理员帐号=-=) 好吧,登陆了服务器我们就有了交互的功能啦可以说是前进了一大步呢!下面能我们就要试 ...
- Openfire XMPP Smack RTC IM 即时通讯 聊天 MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- XMPP(三)-安卓即时通讯客户端
由于时间原因,所以更新比较慢 ,还请大家谅解,此次是对上篇文章中的安卓客户端初级版本进行的一次更新优化,在这次更新后,就有那么一点样子了,可以拿的出手了,呵呵,还在关注的同学也可以及时下载更新.此次主 ...
- 急急如律令!火速搭建一个C#即时通信系统!(附源码分享——高度可移植!)
(2016年3月更:由于后来了解到GGTalk开源即时通讯系统,因此直接采用了该资源用于项目开发,在此对作者表示由衷的感谢!) —————————————————————————————————— 人 ...
随机推荐
- 太可爱了!CSS3 & SVG 制作的米老鼠钟表
米老鼠是大家非常熟悉的迪斯尼动画形象.这是一个可爱的效果,结合 CSS & SVG 图形实现的米老鼠钟表效果.Web 技术让很多生活中的事物都能搬到网上去,后面的推荐阅读也有很多的效果,感兴趣 ...
- Web 开发人员必备的12款 Chrome 扩展程序
之前已经分享过一些帮助 Web 开发人员和设计师的 Chrome 扩展,这次我们继续展示一组很有用的 Chrome 应用程序.这些免费的 Chrome 应用程序可以简化您的工作流程,为了加快您的工作流 ...
- ae IMap接口成员
使用IMap接口显示各种数据源的数据.IMap接口的成员ActiveGraphicsLayer:活动图形图层,如果没有将创建一个基本memory graphics layer.AddLayer:向地图 ...
- 完美解决AutoCAD2012,AutoCAD2013本身电脑里有NET4.0或以上版本却装不上的问题
适用情况:电脑里本身有NET4.0或4.5版本,并且正确安装.或本身你就装有AutoCAD2013或AutoCAD2012要装AutoCAD2012或AutoCAD2013却装不上的情况 如图1所示. ...
- Android悬浮窗实现 使用WindowManager
Android悬浮窗实现 使用WindowManager WindowManager介绍 通过Context.getSystemService(Context.WINDOW_SERVICE)可以获得 ...
- 获取在线APP的素材图片
1.打开iTunes,搜索并下载APP 2.打开下载的APP的路径 4.对ipa包进行解压 5.找到app,右键"显示包内容"进行查看 6.结果
- iOS 播放GIF动态图片!!!!!
////////////////////////////////////////////////////////////////////////////////////////// //// Vie ...
- assign、retain、copy使用异同
1 三者的区别 首先,引用计数的概念:表示对象被引用的次数.当引用计数为 0 的时候,系统就会发送dealloc消息来释放内存. assign:用于基本数据类型,没有引用计数,因此不存在增加或减少引用 ...
- iOS--归档和解档(Archiver)、(UnArchiver)
一.已有类型的归档和解档 首先来看一个简单的例子: //第一方式:归档对象 //对象-->文件 NSArray *array = [NSArray arrayWithObjects:@" ...
- OS开发UI篇—使用UItableview完成一个简单的QQ好友列表
本文转自:http://www.cnblogs.com/wendingding/p/3763330.html 一.项目结构和plist文件 二.实现代码 1.说明: 主控制器直接继承UITableVi ...