最近公司工作比較輕松,就把以前的項目 拿來整理下。以前公司做視頻社交這一塊,類似于YY直播。
### 展示
##### **先來個動態圖**

##### **再簡單看一下主要界面**
首頁第一個界面,這里可以看美女,看直播

這是任務列界面,可以領取每日任務,任務分成長 和推薦

好友列表

用戶的個人中心頁

直播間

用戶的個人中心頁

充值方式頁

銀聯支付頁

### 項目組成
這個項目主要的重點就兩個地方,看視頻,和 與主播互動。
整個視頻流是用RTMP協議的,文字聊天走的是openfire+asmack .
PS:整個項目,我們產品設計的很不錯的,只是我水平有限,有些功能 實現不了!
再介紹下,整個項目都用到了什么?
程序框架:SlidingMenu+Viewpager+fragment
請求服務器: asynchttpclient
解析數據:Gson
消息推送: Jpush
頁面數據分析: Umeng
充值方式: alipay +銀聯+yeepay+短信充值
圖片緩存: afinal
自定義view: Pulltoresfresh+拼音排序聯系人+horizontallistview+verticalviewpager…

另,我把公司的項目寫出來,是因為公司的服務器停掉了,所以,一些數據,是我自己抓出其他應用里面的(抓取數據的方法,在上面一篇文章里)….
首先就是整個項目最下面是mainactivity,這個大家是都有共識的,在mainactivity 上面 我們就要 引入slidingmenu,
關于slidingmenu的下載,就不介紹了,這里直接拿來用
包結構比較清晰

,
整個項目首先,由splashactivity 歡迎界面 ,進行檢查,然后跳轉到mainactivity,mainactivity 中包含slidingmenu,slidingmenu的中間界面 添加了viewpager,viewpager 里面添加了四個fragment。
由于默認v4包里的viewpager 會默認混存數據,即使你設置了setOffscreenPageLimit(0),所以這里替換掉原生的v4包,并且通過fragment 的 setuservisibilityhint 方法來,控制 fragment 界面的動態刷新。
主界面的第一個fragment ,也就是約美女的界面,通過fragmenttabhost,來實現約美女,和看直播的切換。
在約美女中,就是一個簡單地pulltorefreshlistview,適配了一個item.點擊item 進入用戶的個人中心, 個人中心 頂部 是個人的宣傳適配,下面,是用戶自己上傳的 公開專輯,或者私密專輯。可以點贊,關注他。
做任務界面是有兩種任務,一種是 每日任務,就是 登陸,簽到,另一種是下載app 得積分任務。 下載app 可以控制 下載 暫停。
在我的關注界面。是你關注的好友,這個跟微信的聯系人控件是一樣的。首字母排序,用到了比較器。
首先 把漢字,對應首字母提取出來,然后與A-Z 排序。以及特殊字符~。
### 基本代碼
整個項目 基本框架 簡單描述下
在MainActiviy中初始化 slidingmenu。MainActivity 布局文件
`<?xml version="1.0" encoding="utf-8"?>
<com.os.slidingmenu.SlidingMenu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:sliding="http://schemas.android.com/apk/res-auto"
android:id="@+id/slidingmenu"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
sliding:behindOffset="60dp"
sliding:fadeEnabled="true"
sliding:mode="left"
sliding:secondaryShadowDrawable="@drawable/sliding_shadow_right"
sliding:shadowDrawable="@drawable/sliding_shadow_left"
sliding:shadowWidth="10dp"
sliding:touchModeAbove="fullscreen"
sliding:touchModeBehind="margin" />
`
MainActivity這個類進行初始化。
~~~
package com.os.activity;
import java.lang.ref.WeakReference;
import com.os.activity.base.BaseFragmentActivity;
import com.os.activity.base.BaseSlidingFragment;
import com.os.activity.sliding.LeftFragment;
import com.os.activity.sliding.RightFragment;
import com.os.slidingmenu.R;
import com.os.slidingmenu.SlidingMenu;
import com.os.ui.MainHallFragment;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
public class MainActivity extends BaseFragmentActivity {
private Fragment mCurFragment;
public static SlidingMenu mSlidingMenu;
private Handler handler = new MyHandler(this);
private static class MyHandler extends Handler {
private final WeakReference<MainActivity> mActivity;
public MyHandler(MainActivity activity) {
mActivity = new WeakReference<MainActivity>(activity);
}
@Override
public void handleMessage(Message msg) {
MainActivity activity = mActivity.get();
if (activity == null) {
return;
}
activity.handleMsg(msg);
}
}
private void handleMsg(Message msg) {
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initViews();
if (savedInstanceState != null) {
mCurFragment = getSupportFragmentManager().getFragment(savedInstanceState, "mCurContent");
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
getSupportFragmentManager().putFragment(outState, "mCurContent", mCurFragment);
}
private void initViews() {// 通過id 找到slidingmenu
mSlidingMenu = (SlidingMenu) findViewById(R.id.slidingmenu);
mSlidingMenu.setMenu(R.layout.sliding_left_frame);//給slidingmenu 添加左邊的布局
if (getFragmentByTag(LeftFragment.class) == null) {//添加左邊fragment
getSupportFragmentManager().beginTransaction().add(R.id.left_frame, new LeftFragment(), LeftFragment.class.getName()).commit();
}
mSlidingMenu.setContent(R.layout.sliding_center_frame);//添加一個空布局,后面承載 中間的fragment
mSlidingMenu.setSecondaryMenu(R.layout.sliding_right_frame);//添加右面的布局,添加右邊的fragment
if (getFragmentByTag(RightFragment.class) == null) {
getSupportFragmentManager().beginTransaction().add(R.id.right_frame, new RightFragment(), RightFragment.class.getName()).commit();
}
if (mCurFragment != null) {
postSwitchFragment();
}
mSlidingMenu.setTouchModeAbove(SlidingMenu.TOUCHMODE_MARGIN);//設置滑動模式,邊緣 還是整個界面
}
/**
* slidingMenu中的內容Fragment切換(左側菜單觸發)
*
* @param clazz
*/
public void switchCenterFragment(Class<? extends Fragment> clazz) {
try {
if (mSlidingMenu == null) {
removeAllFragments();
return;
}
boolean isInit = false;
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
Fragment userFragment = fm.findFragmentByTag(clazz.getName());
if (userFragment == null) {
isInit = true;
try {
userFragment = clazz.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
if (mCurFragment != null && mCurFragment != userFragment) {
ft.hide(mCurFragment);
}
if (!userFragment.isAdded() && isInit) {
ft.add(R.id.center_frame, userFragment, clazz.getName());
} else {
ft.show(userFragment);
}
ft.commitAllowingStateLoss();
mCurFragment = userFragment;
if (MainHallFragment.class.getName().equals(clazz.getName())) {
mSlidingMenu.setMode(SlidingMenu.LEFT_RIGHT);
if (!isInit) {
((MainHallFragment) userFragment).postScrollTop();
}
} else {
mSlidingMenu.setMode(SlidingMenu.LEFT_RIGHT);
}
postShowContent(200);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* lidingMenu中的內容Fragment內容過濾(右側菜單觸發)
*
* @param clazz
* @param type
*/
public void filterCenterFragment(Class<? extends BaseSlidingFragment> clazz, int type) {
BaseSlidingFragment userFragment = (BaseSlidingFragment) getFragmentByTag(clazz);
if (userFragment != null) {
userFragment.filter(type);
}
if (mSlidingMenu != null)
mSlidingMenu.showContent();
}
/**
* 延遲切換Fragment
*/
private void postSwitchFragment() {
handler.postDelayed(new Runnable() {
@Override
public void run() {
switchCenterFragment(mCurFragment.getClass());
}
}, 50);
}
/**
* 清除FragmentManager中所有Fragment
*/
private void removeAllFragments() {
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
for (int i = 0; i < LeftFragment.FRAGMENTS_CLASSES.length; i++) {
Fragment fragment = getFragmentByTag(LeftFragment.FRAGMENTS_CLASSES[i].getName());
if (fragment != null) {
ft.remove(fragment);
}
}
ft.commitAllowingStateLoss();
}
/**
* 延時mSlidingMenu.showContent()
*
* @param delayMillis 延時時間 單位毫秒
*/
private void postShowContent(long delayMillis) {
handler.postDelayed(new Runnable() {
@Override
public void run() {
if (mSlidingMenu!=null && !MainActivity.this.isFinishing()) {
mSlidingMenu.showContent();
}
}
}, delayMillis);
}
}
~~~
左邊的fragment
~~~
package com.os.activity.sliding;
import java.util.Arrays;
import com.os.activity.MainActivity;
import com.os.activity.base.BaseSlidingFragment;
import com.os.slidingmenu.R;
import com.os.ui.FollowFragment;
import com.os.ui.MainHallFragment;
import com.os.ui.RankFragment;
import android.app.ProgressDialog;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.style.ForegroundColorSpan;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import android.widget.TextView;
import android.widget.Toast;
public class LeftFragment extends BaseSlidingFragment {
private final static int MENU_NORMAL_ICONS[] = { R.drawable.sliding_livehall_icon_normal,
R.drawable.sliding_follow_icon_normal, R.drawable.sliding_rank_icon_normal};
private final static int MENU_CHECKED_ICONS[] = { R.drawable.sliding_livehall_icon_checked,
R.drawable.sliding_follow_icon_checked, R.drawable.sliding_rank_icon_checked };
public final static Class[] FRAGMENTS_CLASSES = { MainHallFragment.class, FollowFragment.class,
RankFragment.class};//左側切換顯示中間的三個界面
private View[] mMenuLayouts;
private ImageView[] mMenuIcons;
private TextView[] mMenuTexts;
private Bitmap mLoadingBitmap;
private int mCurrentIndex = -1;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.sliding_left);
setData();
changeMenuByClass(MainHallFragment.class);//默認中間的界面顯示的是這個MainHallFragment
}
@Override
public void initViews() {
mMenuLayouts = new View[] { findViewById(R.id.menu_livehall_layout),
findViewById(R.id.menu_follow_layout), findViewById(R.id.menu_rank_layout) };
mMenuIcons = new ImageView[] {
(ImageView) findViewById(R.id.menu_livehall_icon), (ImageView) findViewById(R.id.menu_follow_icon), (ImageView) findViewById(R.id.menu_rank_icon) };
mMenuTexts = new TextView[] {
(TextView) findViewById(R.id.menu_livehall_text), (TextView) findViewById(R.id.menu_follow_text), (TextView) findViewById(R.id.menu_rank_text),};
}
@Override
public void addListener() {
for (int i = 0; i < mMenuLayouts.length; i++) {
mMenuLayouts[i].setTag(i);
mMenuLayouts[i].setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
int index = (Integer) v.getTag();
changeMenuByIndex(index);
}
});
}
}
private void setData() {
}
/**
* 通過索引改變Menu
*
* @param index
*/
@SuppressWarnings("unchecked")
private void changeMenuByIndex(int index) {
Class<? extends Fragment> clazz = null;
if (mCurrentIndex != index) {
clearMenu();
setMenuChecked(index);
}
clazz = FRAGMENTS_CLASSES[index];
getFragmentActivity(MainActivity.class).switchCenterFragment(clazz);
mCurrentIndex = index;
}
/**
* 通過Fragment類改變menu
*
* @param clazz
*/
public void changeMenuByClass(Class<? extends Fragment> clazz) {
int index = Arrays.asList(FRAGMENTS_CLASSES).indexOf(clazz);
if (index != -1) {
changeMenuByIndex(index);
}
}
@SuppressWarnings("deprecation")
private void clearMenu() {
for (int i = 1; i <= mMenuLayouts.length; i++) {
mMenuLayouts[i-1].setBackgroundDrawable(null);
mMenuIcons[i - 1].setImageResource(MENU_NORMAL_ICONS[i - 1]);
mMenuTexts[i - 1].setTextColor(getResources().getColor(R.color.gray7));
}
}
private void setMenuChecked(int index) {
// if (index == 0) {
// return;
// }
if (index != 1 && index != 2) {
mMenuLayouts[index].setBackgroundResource(R.drawable.sliding_menu_checked_bg);
}
mMenuIcons[index ].setImageResource(MENU_CHECKED_ICONS[index ]);
mMenuTexts[index ].setTextColor(getResources().getColor(R.color.white));
}
@Override
public void onDestroy() {
if (mLoadingBitmap != null && !mLoadingBitmap.isRecycled()) {
mLoadingBitmap.recycle();
mLoadingBitmap = null;
}
super.onDestroy();
}
}
~~~
主要就是 oncreate 中 初始化 剛啟動應用后中間顯示的fragment 是 MainHallFragment.
視頻時RTMP 協議,解碼用的ffmpeg. 代碼就不貼了,在工程的jni 目錄下,都有注釋。
聊天的代碼 聊天室界面是 ChatroomActivity.
這是 一初始化MultiUserChat 聊天室對象的代碼,具體代碼 ,在這個類里面。
~~~
new Thread() {
public void run() {
try {
Thread.sleep(1 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
int count = 0;
boolean isRandom = false;
while (count <= 10 && !create_flag) {
count++;
try {
if (mHostInfo != null) {
mUserNickName = getNickName(isRandom);
muc = ConnectionUtils.getMultiUserChat(mHostInfo.room_id, mHostInfo.room_service, mUserNickName, mPassword, ChatroomActivity.this);
if (muc != null) {
create_flag = true;
// 創建聊天室成功,監聽聊天室返回的消息
// 監聽消息
muc.addMessageListener(packetListener);
// muc.addParticipantListener(participantListener);
muc.addParticipantStatusListener(statusListener);
muc.addUserStatusListener(userStatusListener);
mHandler.sendEmptyMessageDelayed(9, 500);
} else {
create_flag = false;
}
} else {
create_flag = false;
}
// } else {
//
// }
} catch (NotFoundException e) {
e.printStackTrace();
} catch (SameException e) {// 昵稱重復
isRandom = true;
} catch (BannedException e) {// 禁止加入房間
sendBandHandle(15);
return;
} catch (XMPPException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
~~~