2017-2-8

基本架构

1、使用SurfaceView在UI层面展示视频
2、通过JNI调用C代码控制视频的播放、停止

基本功能

1、从服务器获取正在直播的主播的列表信息

2、进入直播界面

3、可获取的主播信息


Activity_主列表界面

public class MainActivity extends Activity {
    public static final String SERVER_URL = "api.95xiu.com";//"tapi.95xiu.com"
    public static final String RQ_LIVE = "/show/anchor_list_v3.php";
    private List<LiveBean> mList;
    private GridView gridView;
    private MyBaseAdapter adapter;
    private DisplayImageOptions options;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);//取消标题栏
        ImageLoader.getInstance().init(new ImageLoaderConfiguration.Builder(this).build());
        options = new DisplayImageOptions.Builder().cacheInMemory(true).cacheOnDisk(true)//将图片缓存到内存和硬盘中
                .showImageOnLoading(R.drawable.live_icon_default).showImageOnFail(R.drawable.live_icon_default)//加载中、加载错误时显示的图片
                .bitmapConfig(Bitmap.Config.RGB_565).build();
        setContentView(R.layout.layout_main);
        mList = new ArrayList<LiveBean>();
        loadingData();
        gridView = (GridView) findViewById(R.id.gv);
        adapter = new MyBaseAdapter();
        gridView.setAdapter(adapter);
    }

    private void loadingData() {
        RequestParams requestParams = new RequestParams();
        requestParams.put("page_index", "0");//非必须
        requestParams.put("version", "1");//非必须
        AsyncHttpHelper.get(SERVER_URL,RQ_LIVE, requestParams, new OnHttpListener<JSONObject>() {//http://api.95xiu.com/show/anchor_list_v3.php
            @Override
            public void onHttpListener(boolean httpSuccessed, JSONObject obj) {
                if (httpSuccessed) {
                    Log.i("bqt", obj.toString());
                    if (obj.optInt("result") == 1) {
                        JSONArray arr = obj.optJSONArray("user_info");
                        if (arr != null && arr.length() > 0) {
                            for (int i = 0; i < arr.length(); i++) {
                                JSONObject jObject = arr.optJSONObject(i);
                                mList.add(new LiveBean(jObject.optString("anchor_image"), jObject.optString("nickname"), jObject.optString("live_num")//
                                        , jObject.optString("uid")));
                            }
                            Log.i("bqt", "数据个数:" + mList.size());
                        }
                        adapter.notifyDataSetChanged();
                    }
                }
            }
        });
    }

    public class MyBaseAdapter extends BaseAdapter {
        private ViewHolder mViewHolder;
        @Override
        public int getCount() {
            return mList == null ? 0 : mList.size();
        }
        @Override
        public Object getItem(int position) {
            return mList == null ? null : mList.get(position);
        }
        @Override
        public long getItemId(int position) {
            return position;
        }
        @Override
        public View getView(final int position, View convertView, ViewGroup parent) {
            if (convertView != null) mViewHolder = (ViewHolder) convertView.getTag();
            else {
                convertView = LayoutInflater.from(MainActivity.this).inflate(R.layout.item, null);
                mViewHolder = new ViewHolder();
                mViewHolder.iv_head = (ImageView) convertView.findViewById(R.id.iv_anchor_img);
                mViewHolder.tv_name = (TextView) convertView.findViewById(R.id.tv_anchor_name);
                mViewHolder.tv_audience_num = (TextView) convertView.findViewById(R.id.tv_audience_num);
                mViewHolder.iv_rankingLev = (ImageView) convertView.findViewById(R.id.iv_rankingLev);
                mViewHolder.iv_moods = (ImageView) convertView.findViewById(R.id.iv_moods);
                mViewHolder.iv_coverage = (ImageView) convertView.findViewById(R.id.iv_coverage);
                convertView.setTag(mViewHolder);
            }
            if (mList != null) {
                ImageLoader.getInstance().displayImage(mList.get(position).anchor_image, mViewHolder.iv_head, options);
                mViewHolder.tv_name.setText(mList.get(position).nickname);
                mViewHolder.tv_audience_num.setText(mList.get(position).live_num);
                if (position == 0) mViewHolder.iv_rankingLev.setVisibility(View.VISIBLE);
                else mViewHolder.iv_rankingLev.setVisibility(View.INVISIBLE);
                if (position == 0 || position == 1 || position == 3 || position == 6) mViewHolder.iv_moods.setVisibility(View.VISIBLE);
                else mViewHolder.iv_moods.setVisibility(View.INVISIBLE);
                mViewHolder.iv_coverage.setOnClickListener(new OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        Intent intent = new Intent(MainActivity.this, LiveActivity.class);
                        intent.putExtra("anchorId", mList.get(position).anchorId);
                        Log.i("bqt", "主播ID:" + mList.get(position).anchorId);
                        startActivity(intent);
                    }
                });
            }
            return convertView;
        }
    }

    public static class ViewHolder {
        public ImageView iv_head;//主播头像
        public TextView tv_name;//主播名字
        public TextView tv_audience_num;//直播间人数
        public ImageView iv_rankingLev;//排名
        public ImageView iv_moods;//人气等标签
        public ImageView iv_coverage;//背景框
    }
}

class LiveBean {
    public String anchor_image;
    public String nickname;
    public String live_num;
    public String anchorId;
    public LiveBean(String anchor_image, String nickname, String live_num, String anchorId) {
        super();
        this.anchor_image = anchor_image;
        this.nickname = nickname;
        this.live_num = live_num;
        this.anchorId = anchorId;
    }
}

两个布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:baselineAligned="false"
    android:background="#fff"
    android:orientation="horizontal" >
    <GridView
        android:id="@+id/gv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:cacheColorHint="#00000000"
        android:listSelector="#00000000"
        android:verticalSpacing="5dp"
        android:horizontalSpacing="5dp"
        android:descendantFocusability ="beforeDescendants"
        android:numColumns="2" />
</LinearLayout>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/rl_item"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#fbf7ed" >
    <ImageView
        android:id="@+id/iv_anchor_img"
        android:layout_width="match_parent"
        android:layout_height="130dp"
        android:layout_alignParentTop="true"
        android:scaleType="fitXY"
        android:src="@drawable/live_icon_default" />
    <ImageView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@id/iv_anchor_img"
        android:background="@drawable/main_live_head_bg" />
    <TextView
        android:id="@+id/tv_audience_num"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@id/iv_anchor_img"
        android:layout_alignParentLeft="true"
        android:layout_marginBottom="4dp"
        android:drawableLeft="@drawable/living_true"
        android:drawablePadding="4dp"
        android:ellipsize="end"
        android:gravity="center"
        android:paddingLeft="8dp"
        android:singleLine="true"
        android:text="111"
        android:textColor="#00f"
        android:textSize="12sp" />
    <TextView
        android:id="@+id/tv_anchor_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@id/tv_audience_num"
        android:layout_alignParentRight="true"
        android:layout_marginLeft="5dp"
        android:layout_toRightOf="@id/tv_audience_num"
        android:ellipsize="end"
        android:gravity="right"
        android:paddingRight="8dp"
        android:singleLine="true"
        android:text="这是主播主播主播"
        android:textColor="#fff"
        android:textSize="12sp" />
    <ImageView
        android:id="@+id/iv_rankingLev"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="4dp"
        android:layout_marginTop="8dp"
        android:src="@drawable/live_ranking1" />
    <ImageView
        android:id="@+id/iv_moods"
        android:layout_width="40dp"
        android:layout_height="17dp"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:layout_marginTop="8dp"
        android:src="@drawable/live_moods" />
    <ImageView
        android:id="@+id/iv_coverage"
        android:layout_width="match_parent"
        android:layout_height="130dp"
        android:background="@drawable/live_main_item_bg"
        android:clickable="true"
        android:focusable="true" />
</RelativeLayout>

Activity_直播界面

public class LiveActivity extends Activity {
    private ViEAndroidGLES20 mSurfaceView;
    private LinearLayout root;
    private String mVideoUrl;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);//取消标题栏
        initViews();
        setContentView(root);
    }
    private void initViews() {
        // 视频比率 4:3 
        DisplayMetrics displayMetrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
        int width = displayMetrics.widthPixels;
        int h = width * 3 / 4;
        if (h % 2 != 0) h += 1;
        root = new LinearLayout(this);
        root.setOrientation(LinearLayout.VERTICAL);
        mSurfaceView = ViERenderer.CreateRenderer(this, true, null);
        mSurfaceView.setLayoutParams(new FrameLayout.LayoutParams(width, h));//具有父控件的View设置setLayoutParams才有效!
        root.addView(mSurfaceView);
        TextView textView = new TextView(this);
        root.addView(textView);
        Intent intent = getIntent();
        if (intent != null && intent.getStringExtra("anchorId") != null) {
            mVideoUrl = String.format("app/%s?k=1092dc67c9402014144fc19181974172&t=540fb568", intent.getStringExtra("anchorId"));
            textView.setText("视频地址:" + mVideoUrl);
            //livestream.setPlayerStateHandler(mHandler);
            livestream.init(mVideoUrl, mSurfaceView);
            startVideo();
        }
    }

    public void startVideo() {
        try {
            Log.v("vvvv", "startPlay");
            livestream.setVideoPath(mVideoUrl);
            livestream.setSurfaceView(mSurfaceView);
            livestream.playVideo();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public void stopVideo(boolean isFreeHandler) {
        try {
            Log.v("vvvv", "stopPlay");
            livestream.stopVideo();
            if (isFreeHandler) {
                livestream.setPlayerStateHandler(null);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static void freeVideo() {
        try {
            livestream.setPlayerStateHandler(null);
            livestream.free();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onPause() {
        super.onPause();
    }
    @Override
    public void onDestroy() {
        super.onDestroy();
        if (mSurfaceView != null) mSurfaceView.onPause();
        stopVideo(true);
    }
}

清单文件

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.bqt.test"
    android:versionCode="1"
    android:versionName="1.0" >
    <uses-sdk
        android:minSdkVersion="16"
        android:targetSdkVersion="21" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity android:name=".MainActivity" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".LiveActivity" >
        </activity>
    </application>
</manifest>
 

附件列表

直播【95秀】JNI 基本实现 简洁的更多相关文章

  1. 95秀-自定义对话框 dialog 合集

    普通的确认对话框 NormalDialog.java import android.app.Dialog; import android.content.Context; import android ...

  2. 95秀-ViewPager 使用实例

    Activity的样式     <style name="under_live_indicator" parent="android:Theme.NoTitleBa ...

  3. 95秀-异步http请求完整过程

    最终调用时的代码     private void ansyClearApplyInfor() {         RequestParams params = new RequestParams() ...

  4. 95秀-dialog 进度对话框 实用工具

    工具Util public class DialogUtil {     public static ProgressDialogView progressDialog;     /**      * ...

  5. 95秀-PullToRefreshListView 示例

        正在加载.暂无数据页面 public class RefreshGuideTool {     private RelativeLayout rl_loading_guide;//整个View ...

  6. 95秀-弹窗+listview+动画 示例

    Dialog布局 dialog.xml <?xml version="1.0" encoding="utf-8"?> <RelativeLay ...

  7. 做一款仿映客的直播App

    投稿文章,作者:JIAAIR(GitHub) 一.直播现状简介 1.技术实现层面 技术相对都比较成熟,设备也都支持硬编码.iOS还提供现成的Video ToolBox框架,可以对摄像头和流媒体数据结构 ...

  8. 做一款仿映客的直播App?看我就够了

    来源:JIAAIR 链接:http://www.jianshu.com/p/5b1341e97757 一.直播现状简介   1.技术实现层面: 技术相对都比较成熟,设备也都支持硬编码.IOS还提供现成 ...

  9. 开发一款直播APP系统软件应该有哪些功能,如何开发?

    1.技术实现层面: 技术相对都比较成熟,设备也都支持硬编码.IOS还提供现成的 Video ToolBox框架,可以对摄像头和流媒体数据结构进行处理,但Video ToolBox框架只兼容8.0以上版 ...

随机推荐

  1. React Native之DeviceEventEmitter发送和接收消息完成事件处理

    今天在Demo这样一个项目的时候,首先遇到的第一个问题就是,每次通过dialog选择[本周.本月.本天]时,伴随着内容重新渲染的时候,tab navigator每次都重新创建和渲染,造成性能浪费和用户 ...

  2. mongdb 拓展的下载地址和编译安装(php)

    下载地址:https://pecl.php.net/package/mongodb 编译安装: $ tar zxvf mongodb-mongodb-php-driver-<commit_id& ...

  3. BZOJ 2330 SCOI2011糖果 差分约束

    2330: [SCOI2011]糖果 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2819  Solved: 820 题目连接 http://www ...

  4. 证明 O(n/1+n/2+…+n/n)=O(nlogn)

    前言 在算法中,经常需要用到一种与调和级数有关的方法求解,在分析该方法的复杂度时,我们会经常得到\(O(\frac{n}{1}+\frac{n}{2}+\ldots+\frac{n}{n})\)的复杂 ...

  5. Linux学习之CentOS(十三)--CentOS6.4下Mysql数据库的安装与配置(转)

    原文地址:http://www.cnblogs.com/xiaoluo501395377/archive/2013/04/07/3003278.html 如果要在Linux上做j2ee开发,首先得搭建 ...

  6. PHP通过AJAX及Access-Control-Allow-Origin实现跨域访问

    这里的跨域实质上是由浏览器同源策略限制的一类请求场景,浏览器同源策略SOP(Same origin policy)是一种约定,由Netscape公司1995年引入浏览器,它是浏览器最核心也最基本的安全 ...

  7. vue-router query和params传参(接收参数),$router、$route的区别

    链接:https://segmentfault.com/a/1190000012735168 1.query方式传参和接收参数 传参: this.$router.push({ path:'/xxx' ...

  8. Linux终端(Xshell等)的编码设置

    先简单说说一下遇到的情况吧: 在用类似Xshell的工具连接远端Linux时,运行命令ls时,如果有中文,就会显示有乱码: 网上查资料时,也把相应的连接属性修改为utf-8了(见下图),但是还是不行: ...

  9. POJ 1330 Nearest Common Ancestors (LCA,倍增算法,在线算法)

    /* *********************************************** Author :kuangbin Created Time :2013-9-5 9:45:17 F ...

  10. perf 工具介绍1

    https://perf.wiki.kernel.org/index.php/Tutorial http://os.51cto.com/art/201105/265133.htm 在LINUX 源代码 ...