J哥---------公司(视频 社交)项目分享

最近公司工作比较轻松,就把以前的项目 拿来整理下。以前公司做视频社交这一块,类似于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();
                    }
                }

具体业务代码,工程里面找吧。有需要的可以看下,找工作的时候用。关于项目的其他问题可以Q我。

对了,由于公司服务器停了,所以自己注册用户的借口也挂了,注册不成功,点击 那个一键注册的,还可以,就是发送一条短信息(1毛钱),然后就进入界面了。

PS: 反正服务器都停了,就贡献出来,找工作也算多个项目。

完整代码:http://download.csdn.net/detail/u011733020/8875855

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-09 05:57:27

J哥---------公司(视频 社交)项目分享的相关文章

4G来临,短视频社交分享应用或井喷

因为工作的原因,接触短视频社交应用的时间相对较多,不管是自家的微视,还是别人家的Vine.玩拍.秒拍等,都有体验过.随着时间的推移,我愈发感受到有一股似曾相识的势能正在某个地方慢慢积聚,直到今天我才猛然醒悟,原来所谓势能就是曾经伴随着早期微博和微信崛起的那些大账号,所谓的某个地方就是诸如Vine.微视.玩拍这样的短视频.   势能的崛起,对于产品的发展.成熟应该是一件好事,但是也不能过于乐观和依赖,这个我在后面会详细讲到.下面我先讲一下为什么看好短视频分享: 1.视频比文字.图片更让人回味无穷

从游戏语音到视频社交,一文详解2017实时互联网最热技术

2017 已过大半,从年初盛起的<王者荣耀>.<狼人杀>却依然是最火爆的游戏产品,其共同特性都在于集成了实时语音功能,前者左手走位右手技能,语音自然也就成为了非常必要的属性,而后者更不用说,本就是纯粹依靠实时语音进行下去的游戏. 而从游戏到直播.在线教育/医疗以及 VR/AR.AI 等互联网垂直行业及创新技术,这样的例子还有很多.比如转型做直播的陌陌在最新的 8.0 版本中推出了“快聊”.“狼人杀”.“派对”等实时视频社交玩法:小米在新发布智能音箱中也集成了实时语音云服务.随着互联

Android--上百个Android开源项目分享

上百个Android开源项目分享,希望对android开发有帮助. Android PDF 阅读器 http://sourceforge.net/projects/andpdf/files/ 个人记账工具 OnMyMeans http://sourceforge.net/projects/onmymeans/develop Android电池监控 Android Battery Dog http://sourceforge.net/projects/andbatdog/ RSS阅读软件 Andr

【技术分享会】谈谈公司内部的技术分享

这段时间,为了促进程序同事间技术氛围,在公司内部组织开展技术分享会.形式很简单,每周进行一次技术分享:分享人由组员顺序安排:题材不限,可以是自己熟悉的技术,比如说服务端的开发者,分享后端定时器,消息队列等等,前端的开发者分享加载的模式,MVC模式等等,可以是一些通用的技术,比如数据结构,算法,代码风格,Effective 系列,调试技巧等,甚至可以是经典书的读后感等等,抑或是最近大家在研究一个开源的项目,也可以跟大家讲一下这个开源项目的框架:或许有些人利用业余时间做了一个小软件,也可以拿出来分享

&lt;转&gt;国内一些大公司的开源项目

昨天看阿里的MetaQ文档,感觉对于消息系统的理解,比起大多数文章都要出色得多了,有些分析也非常的有实用性.估计还有很多优秀的项目没被发掘,于是就调研了一下,国内一些大公司的开源项目. 阿里 阿里的开源项目很多,这也跟@淘宝正明的开源态度密不可分.有很多重量级的项目,例如LVS.Tengine,或者很有实践价值的中间件,例如MetaQ(分布式消息系统).dubbo(RPC框架).cobar(数据库中间件),或者是Java世界的工具,例如druid.fastjson.都说国内Java公司的技术架构

500G JAVA视频网盘分享 (Jeecg社区)

http://blog.csdn.net/zhangdaiscott/article/details/18220411    csdn 排名400多名 500 G JAVA视频网盘分享(Jeecg社区) [涵盖从java入门到深入架构,Linux.云计算.分布式.大数据Hadoop.ios.Android.互联网技术应有尽有] Jeecg社区秉承开源宗旨,分享社区Java架构视频,更多资料点击: www.jeecg.org JAVA架构QQ技术群: 39596137 师徒架构班: 开源社区师徒架

600G视频开发资料分享给大家

1.最全面的Android视频开发资料共享(传智播客,极客学院,老罗)基础+高级+项目实战,持续更新....点击打开链接http://pan.baidu.com/s/1dDdaoCD 2.ios视频开发教程分享(swift+基础+高级+项目实战),持续更新中....点击打开链接   http://pan.baidu.com/s/1hqxSQuK ; 3.javaweb开发视频资料(基础+高级+项目实战)包含ssh+全文检索+webservice+商城项目等  持续更新..点击打开链接http:/

手机游戏渠道SDK接入工具项目分享(二)万事开头难

一般接到任务后程序员们通常都开始着手进行技术调研了,但我这活是项目负责人.还有一大堆事情要先期准备,没人能帮忙. 一.人力配置 考虑的之前已经有一波人搞了大半年,但没有起色,先期也没有太大人力需求,所以不指望这批人了.因为是外包收钱按人头工时算,所以拉几个自己兄弟填坑. 初期人力配置 服务端x 1.Android x 1 二.开发需求 自己手机游戏CP作了3年,需求直接写完后让对方确认,一次通过. 1.      公司多款游戏都需要使用这套工具,需要作适配兼容,还好都是Unity3D项目.之后我

在较成熟的中大型公司做创业项目,是种什么样的体验?

在体制发展较成熟的中大型公司里,搞创业项目,也是创业的一种姿态. 记得之前经常会碰到一些即将毕业的或者面临择业的朋友,会问到“依照现在国内互联网公司发展的情况,现在选择去一些较成熟的公司,如BAT这类的公司更好呢,还是选择去一些创业公司更好呢?” 很多专业的职业规划指导师,都会列出N条这样选择或者那样选择的优缺点,但是今天我想和大家分享另外一种工作的姿态,如标题所示. 什么样的公司称得上较成熟的中大型公司呢?这个当然也没有统一标准,不过按照目前国内互联网公司的现状来说的话,除了以BAT为首的大佬