android 练习之路
Posted Qunter
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了android 练习之路 相关的知识,希望对你有一定的参考价值。
项目的github地址:https://github.com/Qunter/SearchAndCall
------------------------------------------------------------------------
上图
PS:也不知道为什么,自从加了融云之后在虚拟机里使用的时候一直会报俩错,估计应该是跟6.0的适配有关吧,不过真机不报错,并且也不影响使用,那就先这样放着吧
PPS:一开始账号打错了,我还真是老年人记忆力......囧
今天使用Bmob来实现好友关系的存储,融云的IM来实现好友间的聊天
先做好准备工作,融云的依赖添加好,首先是下最新的kit包,然后导入两个module,并且添加依赖
//融云IM依赖 compile project(\':IMKit\')
这里还有一些相关的设置,暂且不说,官网上有文档
这还不算完,因为这个程序里我们没有后台(竞赛提交作品要能直接演示,当然了,客观原因是我也不是很喜欢挂后台,挺麻烦的),所以我们得在客户端里实现后台的功能,所以我们需要导入一些融云的工具类
它们在哪下载呢,可以下载一个java的融云的后台demo,然后把其中的io.rong包复制过来,粘贴到项目里
这就算把先头工作做的差不多了,然后一步一步来
还是类似上一个活动模块的布局样式
activity_friend_info_fragm.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.design.widget.TabLayout android:id="@+id/friendTabLayout" android:layout_width="match_parent" android:layout_height="45dp" app:tabIndicatorColor="@android:color/black"/> <android.support.v4.view.ViewPager android:id="@+id/friendViewPaper" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1"/> </LinearLayout>
布局完了就是跟一个Activity
FriendInfoFragmActivity.java
public class FriendInfoFragmActivity extends Fragment { public static FriendInfoFragmActivity newInstance() { return new FriendInfoFragmActivity(); } @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.activity_friend_info_fragm, container, false); //Fragment+ViewPager+FragmentViewPager组合的使用 ViewPager viewPager = (ViewPager) view.findViewById(R.id.friendViewPaper); FriendPagerAdapter adapter = new FriendPagerAdapter(getActivity().getSupportFragmentManager(), getContext()); viewPager.setAdapter(adapter); //TabLayout TabLayout tabLayout = (TabLayout) view.findViewById(R.id.friendTabLayout); tabLayout.setupWithViewPager(viewPager); return view; } }
接着是建一个viewpager的adapter
FriendPagerAdapter.java
public class FriendPagerAdapter extends FragmentPagerAdapter { public final int COUNT = 2; private String[] titles = new String[]{"消息列表", "我的好友"}; private Context context; private Fragment conversationList; private Fragment conversationFragment = null; public FriendPagerAdapter(FragmentManager fm, Context context) { super(fm); this.context = context; } @Override public Fragment getItem(int position) { if(position==0){ conversationList = initConversationList();//获取融云会话列表的对象 return conversationList; }else if(position==1){ return FriendPageFragment.newInstance(); } return null; } @Override public int getCount() { return COUNT; } @Override public CharSequence getPageTitle(int position) { return titles[position]; } private Fragment initConversationList() { /** * appendQueryParameter对具体的会话列表做展示 */ if (conversationFragment == null) { ConversationListFragment listFragment = new ConversationListFragment(); Uri uri = Uri.parse("rong://" + context.getPackageName()).buildUpon() .appendPath("conversationList") .appendQueryParameter(Conversation.ConversationType.PRIVATE.getName(), "false")//设置私聊会话是否聚合显示 .appendQueryParameter(Conversation.ConversationType.GROUP.getName(), "true") // .appendQueryParameter(Conversation.ConversationType.PUBLIC_SERVICE.getName(), "false")//公共服务号 //.appendQueryParameter(Conversation.ConversationType.APP_PUBLIC_SERVICE.getName(), "false")//公共服务号 .appendQueryParameter(Conversation.ConversationType.DISCUSSION.getName(), "false")//设置私聊会话是否聚合显示 .appendQueryParameter(Conversation.ConversationType.SYSTEM.getName(), "false")//设置私聊会是否聚合显示 .build(); listFragment.setUri(uri); return listFragment; } else { return conversationFragment; } } }
左边是消息列表,这个用融云的消息列表,右边是好友列表,就需要我们自己定义了
从左至右吧
融云的消息列表
activity_conversation.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#000"> <TextView android:id="@+id/name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_margin="15dp" android:text="rongCloud" android:textColor="#fff" android:textSize="18sp" /> </LinearLayout> <fragment android:id="@+id/conversation" android:name="io.rong.imkit.fragment.ConversationFragment" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
然后是Activity
(不是我说,这个命名是真的有毒,这个类是从融云提供的demo上摘下来的,不过反正是他们内部实现的东西,先不改得了,忙完这两天再一起弄)
public class ConversationActivity extends FragmentActivity { private TextView mName; //private ImageView mPersionInformationIv; private Conversation.ConversationType mConversationType; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_conversation); Intent intent = getIntent(); mConversationType = Conversation.ConversationType.valueOf(intent.getData().getLastPathSegment().toUpperCase(Locale.getDefault())); //Log.e("log", mConversationType.getName()); mName = (TextView) findViewById(R.id.name); /* mPersionInformationIv = (ImageView) findViewById(R.id.persionInformationIv); if(mConversationType.getName().equals("private")){ mPersionInformationIv.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent mIntent = new Intent(getApplicationContext(),UserInformationPage.class); Bundle bundle=new Bundle(); bundle.putString("userNickName", getIntent().getData().getQueryParameter("title")); mIntent.putExtras(bundle); startActivity(mIntent); } }); }else if(mConversationType.getName().equals("discussion")){ mPersionInformationIv.setVisibility(View.GONE); } */ String sId = getIntent().getData().getQueryParameter("targetId");//targetId:单聊即对方ID,群聊即群组ID String sName = getIntent().getData().getQueryParameter("title");//获取昵称 if (!TextUtils.isEmpty(sName)){ mName.setText(sName); }else { // sId //TODO 拿到id 去请求自己服务端 } } }
然后这个界面注册的方式不一样,这里也贴一下,其实官方文档有写
<!--会话界面--> <activity android:name=".activity.ConversationActivity" android:screenOrientation="portrait" android:windowSoftInputMode="stateHidden|adjustResize"> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <data android:host="com.qunter.searchcall" android:pathPrefix="/conversation/" android:scheme="rong" /> </intent-filter> </activity>
然后就是好友列表的实现
activity_friend_list.xml
<?xml version="1.0" encoding="utf-8"?> <android.support.v4.widget.SwipeRefreshLayout android:id="@+id/swipe_refresh_friend" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.RecyclerView android:id="@+id/recycler_friend" android:layout_width="match_parent" android:layout_height="match_parent" android:overScrollMode="never" android:scrollbars="vertical" /> </android.support.v4.widget.SwipeRefreshLayout>
item_friend_info.xml
<?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.CardView android:id="@+id/friend_card_view" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="60dp" android:layout_marginBottom="2dp" android:layout_marginTop="2dp" android:clickable="true" app:cardBackgroundColor="@color/card_view_background_dark" app:cardCornerRadius="0dp" app:cardElevation="2dp"> <LinearLayout android:id="@+id/item_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="10dp" android:orientation="horizontal"> <ImageView android:id="@+id/item_useravatar" android:layout_width="40dp" android:layout_height="40dp" android:layout_marginLeft="30dp" android:layout_marginRight="10dp" android:scaleType="fitCenter" android:src="@drawable/account_avatar" /> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/item_username" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:layout_marginEnd="10dp" android:lineSpacingExtra="2dp" android:maxLines="1" android:padding="2dp" android:textColor="@color/font_normal" android:textSize="18sp" /> </RelativeLayout> </LinearLayout> </android.support.v7.widget.CardView>
左边直接new一个融云的会话列表就行,但是右边需要自己写
FriendPageFragment.java
public class FriendPageFragment extends Fragment implements RongIM.UserInfoProvider{ private SwipeRefreshLayout friendSwipeRefreshLayout; private FriendInfoListAdapter adapter; private List<UserInfo> loginUserFriendInfoList; private List<Friend> loginUserFriendRongList; private RecyclerView friendRecyclerView; private String loginUserFriendObjectID=""; private final int GETLOGINUSERFRIENDOBJECTID=0x00,GETLOGINUSERFRIENDLIST=0x01,FRIENDINFORMATIONLISTDOWNOVER=0x02; private Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what){ case GETLOGINUSERFRIENDOBJECTID: getLoginUserFriendObjectID(); break; case GETLOGINUSERFRIENDLIST: getLoginUserFriendList(); break; case FRIENDINFORMATIONLISTDOWNOVER: loadFriendRecycleView(); initUserInfo(); friendSwipeRefreshLayout.setRefreshing(false); break; } } }; public static FriendPageFragment newInstance() { FriendPageFragment fragment = new FriendPageFragment(); return fragment; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.activity_friend_list,container,false); friendSwipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.swipe_refresh_friend); friendSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { handler.sendEmptyMessage(GETLOGINUSERFRIENDLIST); } }); friendRecyclerView = (RecyclerView) view.findViewById(R.id.recycler_friend); LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity()); friendRecyclerView.setLayoutManager(layoutManager); handler.sendEmptyMessage(GETLOGINUSERFRIENDOBJECTID); return view; } /** * 获取用户好友列表的数据库表单中ID */ private void getLoginUserFriendObjectID(){ final BmobQuery<UserFriend> userObjectIDQuery = new BmobQuery<UserFriend>(); userObjectIDQuery.addWhereEqualTo("userID", BmobUser.getCurrentUser(UserInfo.class).getUserPhone()); userObjectIDQuery.findObjects(new FindListener<UserFriend>() { @Override public void done(List<UserFriend> object, BmobException e) { if(e==null){ loginUserFriendObjectID =object.get(0).getObjectId(); //Toast.makeText(getContext(), "loginUserFriendObjectID"+loginUserFriendObjectID, Toast.LENGTH_SHORT).show(); handler.sendEmptyMessage(GETLOGINUSERFRIENDLIST); }else{ } } }); } /** *获取用户好友列表数据 */ private void getLoginUserFriendList(){ UserFriend userFriend = new UserFriend(); // 查询好友列表内的所有用户,因此查询的是用户表 BmobQuery<UserInfo> userFriendQuery = new BmobQuery<UserInfo>(); userFriend.setObjectId(loginUserFriendObjectID); //userFriend是UserFriend表中的字段,用来存储所有该用户的好友关系的用户 userFriendQuery.addWhereRelatedTo("userFriend", new BmobPointer(userFriend)); userFriendQuery.findObjects(new FindListener<UserInfo>() { @Override public void done(List<UserInfo> object,BmobException e) { if(e==null){ loginUserFriendInfoList=object; Log.e("taggg", loginUserFriendInfoList.size()+"" ); Log.e("taggg", loginUserFriendInfoList.get(0).getUserNickname()+"" ); //Toast.makeText(getContext(), "成功加载好友列表数据"+userFriendInformationList.size(), Toast.LENGTH_SHORT).show(); handler.sendEmptyMessage(FRIENDINFORMATIONLISTDOWNOVER); }else{ Toast.makeText(getContext(), "加载好友列表数据失败"+e, Toast.LENGTH_SHORT).show(); } } }); } /** * 加载好友信息至RecycleView */ private void loadFriendRecycleView(){ adapter = new FriendInfoListAdapter(getContext(),loginUserFriendInfoList,friendRecyclerView); adapter.setOnItemClickListener(new FriendInfoListAdapter.OnItemClickListener() { @Override public void onItemClick(View view, int position) { RongIM.getInstance().startPrivateChat(getContext(), loginUserFriendInfoList.get(position).getUserPhone(), loginUserFriendInfoList.get(position).getUserNickname()); } }); friendRecyclerView.setAdapter(adapter); } /** * 储存好友相关信息:id,昵称,token */ private void initUserInfo() { loginUserFriendRongList = new ArrayList<Friend>(); loginUserFriendRongList.add(new Friend(BmobUser.getCurrentUser(UserInfo.class).getUserPhone(),BmobUser.getCurrentUser(UserInfo.class).getUserNickname(),BmobUser.getCurrentUser(UserInfo.class).getUserAvatar())); for(UserInfo userFriendInfo:loginUserFriendInfoList){ //好友内容为:id,昵称,头像url loginUserFriendRongList.add(new Friend(userFriendInfo.getUserPhone(),userFriendInfo.getUserNickname(),userFriendInfo.getUserAvatar())); } RongIM.setUserInfoProvider(this, true); } @Override public io.rong.imlib.model.UserInfo getUserInfo(String s) { for (Friend i : loginUserFriendRongList) { if (i.getUserId().equals(s)) { //Log.e(TAG, i.getPortraitUri()); return new io.rong.imlib.model.UserInfo(i.getUserId(), i.getName(), Uri.parse(i.getPortraitUri())); } } return null; } }
然后就需要写一个RecycleView的Adapter了
FriendInfoListAdapter.java
public class FriendInfoListAdapter extends RecyclerView.Adapter<FriendInfoListAdapter.ViewHolder>{ private List<UserInfo> loginUserFriendInfoList; private Context context; private RecyclerView recyclerView; private OnItemClickListener onItemClickListener; static class ViewHolder extends RecyclerView.ViewHolder{ private ImageView userAvatarImg; private TextView userNameTv; public ViewHolder(View view){ super(view); userAvatarImg = (ImageView) view.findViewById(R.id.item_useravatar); userNameTv = (TextView) view.findViewById(R.id.item_username); } } public FriendInfoListAdapter(Context context,List<UserInfo> loginUserFriendInfoList,RecyclerView recyclerView){ this.context = context; this.loginUserFriendInfoList = loginUserFriendInfoList; this.recyclerView = recyclerView; } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_friend_info,parent,false); ViewHolder holder = new ViewHolder(view); return holder; } @Override public void onBindViewHolder(final FriendInfoListAdapter.ViewHolder holder, final int position) { holder.setIsRecyclable(false); final UserInfo friendInfo = loginUserFriendInfoList.get(position); Glide.with(context).load(friendInfo.getUserAvatar()).bitmapTransform(new CropCircleTransformation(context)).into(holder.userAvatarImg); holder.userNameTv.setText(friendInfo.getUserNickname()); if(onItemClickListener != null){ //为ItemView设置监听器 holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int position = holder.getLayoutPosition(); onItemClickListener.onItemClick(holder.itemView,position); } }); } } @Override public int getItemCount() { return loginUserFriendInfoList.size(); } /** * 点击事件接口 */ public interface OnItemClickListener{ void onItemClick(View view, int position); } /** * 设置点击事件方法 */ public void setOnItemClickListener(OnItemClickListener onItemClickListener){ this.onItemClickListener = onItemClickListener; } }
然后回头看一眼,首先在MainActivity里应该初始化融云的服务
RongIM.init(this); initUserToken();
/** * 获取融云所需userID及token */ private void initUserToken(){ UserInfo loginUser = BmobUser.getCurrentUser(UserInfo.class); userID = loginUser.getUserPhone(); connectRongServer(loginUser.getRongToken()); } /** * 初始化登录用户的融云服务 */ private void connectRongServer(String token) { RongIM.connect(token, new RongIMClient.ConnectCallback() { @Override public void onSuccess(String userId) { if (userId.equals(userID)){ Toast.makeText(getApplicationContext(), userID+"成功连接", Toast.LENGTH_SHORT).show(); }else { Toast.makeText(getApplicationContext(), userID+"连接失败", Toast.LENGTH_SHORT).show(); } } @Override public void onError(RongIMClient.ErrorCode errorCode) { // Log.e("onError", "onError userid:" + errorCode.getValue());//获取错误的错误码 Toast.makeText(getApplicationContext(), "Error", Toast.LENGTH_SHORT).show(); Log.e("MainActivity", "connect failure errorCode is : " + errorCode.getValue()); } @Override public void onTokenIncorrect() { Toast.makeText(getApplicationContext(), "TokenError", Toast.LENGTH_SHORT).show(); Log.e("MainActivity", "token is error ,please check token and appkey"); } }); }
实体类也需要完善一下了,我们现在还有很多其他需要的字段,以及融云所需的好友实体
UserInfo.java
public class UserInfo extends BmobUser { private String userNickname; private String userPhone; private String rongToken; //用户头像,先设置初始头像 private String userAvatar="http://bmob-cdn-8854.b0.upaiyun.com/2017/01/21/910615c0405f9bd280350b57f8dc180c.png"; public String getUserNickname() { return userNickname; } public void setUserNickname(String userNickname) { this.userNickname = userNickname; } public String getUserPhone() { return userPhone; } public void setUserPhone(String userPhone) { this.userPhone = userPhone; } public String getRongToken() { return rongToken; } public void setRongToken(String rongToken) { this.rongToken = rongToken; } public String getUserAvatar() { return userAvatar; } public void setUserAvatar(String userAvatar) { this.userAvatar = userAvatar; } }
UserFriend.java
public class UserFriend extends BmobObject { private String userID; private BmobRelation userFriend; public BmobRelation getUserFriend() { return userFriend; } public void setUserFriend(BmobRelation userFriend) { this.userFriend = userFriend; } public String getUserID() { return userID; } public void setUserID(String userID) { this.userID = userID; } }
Friend.java
public class Friend { private String userId; private String name; private String portraitUri; public String getUserId() { return userId; } public void setUserId(String userId) { this.userId = userId; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPortraitUri() { return portraitUri; } public void setPortraitUri(String portraitUri) { this.portraitUri = portraitUri; } public Friend(String userId, String name, String portraitUri) { this.userId =以上是关于android 练习之路 的主要内容,如果未能解决你的问题,请参考以下文章