欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

android项目接入阿里视频直播实例详解

程序员文章站 2022-07-02 09:22:53
一、简介目前很多APP都含有自己的视频直播功能,市场上大家比较熟悉的是阿里和腾讯的两款直播服务,最初我选的视腾讯云直播集成方法也很简单,后来发现水印无法去除可以自定义,,项目要求无水印,交涉后组长说需要付费才能去除,直播画面画质不太好,免费版特别虚;因此转而使用阿里的直播服务,集成方法很简单,比较顺利。二、包引用1.根据文档来功能快捷键撤销:Ctrl/Command + Z重做:Ctrl/Command + Y加粗:Ctrl/Command + B斜体:Ctrl/Command + I标题...

一、简介

目前很多APP都含有自己的视频直播功能,市场上大家比较熟悉的是阿里和腾讯的两款直播服务,最初我选的视腾讯云直播集成方法也很简单,后来发现水印无法去除可以自定义,,项目要求无水印,交涉后组长说需要付费才能去除,直播画面画质不太好,免费版特别虚;因此转而使用阿里的直播服务,集成方法很简单,比较顺利。

二、包引用

1.根据文档来:http://docs-aliyun.cn-hangzhou.oss.aliyun-inc.com/assets/attach/137410/cn_zh/1583376879936/%E7%9B%B4%E6%92%AD%E6%8E%A8%E6%B5%81SDK%E5%BC%80%E5%8F%91%E6%96%87%E6%A1%A3%281%29.pdf?spm=a2c4g.11186623.2.11.40e14cce9yPVoE&file=%E7%9B%B4%E6%92%AD%E6%8E%A8%E6%B5%81SDK%E5%BC%80%E5%8F%91%E6%96%87%E6%A1%A3%281%29.pdf

2.在官网上把.so文件下载下来,放到自己的lib下
android项目接入阿里视频直播实例详解
3.直播要用的aar和jar包放到相应的目录下,官网上有下载,美颜,人脸等jar可以根据自己项目需要添加。
android项目接入阿里视频直播实例详解

三、开始使用

1.build.gradle文件添加依赖: implementation files(‘libs/live-face-3.4.0.jar’)
implementation files(‘libs/commons-lang3-3.0.jar’)
implementation ‘com.aliyun.dpa:oss-android-sdk:+’;文中有关于aar包的添加,同样需要在build.gradle文件中引用,在build.gradle写全局引用。
android项目接入阿里视频直播实例详解
android项目接入阿里视频直播实例详解
2.集成系统要求最小API:15
android项目接入阿里视频直播实例详解
3.不要忘了在manifest文件中打开权限,除了网络,读写以及相机权限,打开手电筒
可以使用闪光灯功能,注意:android6.0以后部分权限需要代码开启。

4.准备就绪后就开始开始自己的视频推流业务了,布局文件可以根据自家UI设计来,我这边用一个LivePushActivity接收和设置推流配置,嵌套一个Fragment实现具体推流逻辑;默认推流设置

private AlivcLivePushConfig getPushConfig() {
        mAlivcLivePushConfig.setResolution(mDefinition);
        mAlivcLivePushConfig.setInitialVideoBitrate(1400);

        mAlivcLivePushConfig.setAudioBitRate(1000 * 64);

        mAlivcLivePushConfig.setMinVideoBitrate(600);
        mAlivcLivePushConfig.setTargetVideoBitrate(1400);

        mAlivcLivePushConfig.setConnectRetryCount(5);

        mAlivcLivePushConfig.setConnectRetryInterval(16);
        mAlivcLivePushConfig.setFps(FPS_25);
        mAlivcLivePushConfig.setCameraType(AlivcLivePushCameraTypeEnum.CAMERA_TYPE_BACK);//后置摄像头
        mAlivcLivePushConfig.setPreviewDisplayMode(AlivcPreviewDisplayMode.ALIVC_LIVE_PUSHER_PREVIEW_ASPECT_FILL);//全屏剪裁模式

        return mAlivcLivePushConfig;
    }

```java
public class LivePushActivity extends AppCompatActivity {
    private static final String TAG = "LivePushActivity";
    private static final int FLING_MIN_DISTANCE = 50;
    private static final int FLING_MIN_VELOCITY = 0;
    private final long REFRESH_INTERVAL = 1000;
    private static final String URL_KEY = "url_key";
    private static final String ASYNC_KEY = "async_key";
    private static final String AUDIO_ONLY_KEY = "audio_only_key";
    private static final String VIDEO_ONLY_KEY = "video_only_key";
    private static final String ORIENTATION_KEY = "orientation_key";
    private static final String CAMERA_ID = "camera_id";
    private static final String FLASH_ON = "flash_on";
    private static final String AUTH_TIME = "auth_time";
    private static final String PRIVACY_KEY = "privacy_key";
    private static final String MIX_EXTERN = "mix_extern";
    private static final String MIX_MAIN = "mix_main";
    public static final int REQ_CODE_PUSH = 0x1112;
    public static final int CAPTURE_PERMISSION_REQUEST_CODE = 0x1123;

    public SurfaceView mPreviewView;
    private ViewPager mViewPager;

    private List<Fragment> mFragmentList = new ArrayList<>();
    private FragmentAdapter mFragmentAdapter;

    private GestureDetector mDetector;
    private ScaleGestureDetector mScaleDetector;
    private LivePushFragment mLivePushFragment;

    private AlivcLivePushConfig mAlivcLivePushConfig;

    private AlivcLivePusher mAlivcLivePusher = null;
    private String mPushUrl = null;

    private boolean mAsync = false;
    private boolean mAudioOnly = false;
    private boolean mVideoOnly = false;
    private int mOrientation = ORIENTATION_PORTRAIT.ordinal();

    private SurfaceStatus mSurfaceStatus = SurfaceStatus.UNINITED;
    //    private Handler mHandler = new Handler();
    private boolean isPause = false;

    private int mCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT;
    private boolean mFlash = false;
    private boolean mMixExtern = false;
    private boolean mMixMain = false;
    AlivcLivePushStatsInfo alivcLivePushStatsInfo = null;
    TaoBeautyFilter taoBeautyFilter;

    TaoFaceFilter taoFaceFilter;

    private String mAuthTime = "";
    private String mPrivacyKey = "";

    //    private ConnectivityChangedReceiver mChangedReceiver = new ConnectivityChangedReceiver();
    private boolean videoThreadOn = false;
    private boolean audioThreadOn = false;

    private int mNetWork = 0;

    private JsonsRootBean liveInfoBeanData = null;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        EventBus.getDefault().register(this);

        mPushUrl = getIntent().getStringExtra(URL_KEY);
        mAsync = getIntent().getBooleanExtra(ASYNC_KEY, false);
        mAudioOnly = getIntent().getBooleanExtra(AUDIO_ONLY_KEY, false);
        mVideoOnly = getIntent().getBooleanExtra(VIDEO_ONLY_KEY, false);
        mOrientation = getIntent().getIntExtra(ORIENTATION_KEY, ORIENTATION_PORTRAIT.ordinal());
        mCameraId = getIntent().getIntExtra(CAMERA_ID, Camera.CameraInfo.CAMERA_FACING_FRONT);
        mFlash = getIntent().getBooleanExtra(FLASH_ON, false);
        mAuthTime = getIntent().getStringExtra(AUTH_TIME);
        mPrivacyKey = getIntent().getStringExtra(PRIVACY_KEY);
        mMixExtern = getIntent().getBooleanExtra(MIX_EXTERN, false);
        mMixMain = getIntent().getBooleanExtra(MIX_MAIN, false);
        liveInfoBeanData = (JsonsRootBean) getIntent().getSerializableExtra("liveInfo");
        setOrientation(mOrientation);
        setContentView(R.layout.activity_push);
        initView();
        mAlivcLivePushConfig = (AlivcLivePushConfig) getIntent().getSerializableExtra(AlivcLivePushConfig.CONFIG);
        mAlivcLivePusher = new AlivcLivePusher();

        try {
            mAlivcLivePusher.init(getApplicationContext(), mAlivcLivePushConfig);
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
            showDialog(this, e.getMessage());
        } catch (IllegalStateException e) {
            e.printStackTrace();
            showDialog(this, e.getMessage());
        }

        mAlivcLivePusher.setCustomDetect(new AlivcLivePushCustomDetect() {
            @Override
            public void customDetectCreate() {
                taoFaceFilter = new TaoFaceFilter(getApplicationContext());
                taoFaceFilter.customDetectCreate();
            }

            @Override
            public long customDetectProcess(long data, int width, int height, int rotation, int format, long extra) {
                if (taoFaceFilter != null) {
                    return taoFaceFilter.customDetectProcess(data, width, height, rotation, format, extra);
                }
                return 0;
            }

            @Override
            public void customDetectDestroy() {
                if (taoFaceFilter != null) {
                    taoFaceFilter.customDetectDestroy();
                }
            }
        });


        mLivePushFragment = new LivePushFragment().newInstance(mPushUrl, mAsync, mAudioOnly, mVideoOnly, mCameraId, mFlash, mAlivcLivePushConfig.getQualityMode().getQualityMode(), mAuthTime, mPrivacyKey, mMixExtern, mMixMain);
        mLivePushFragment.setAlivcLivePusher(mAlivcLivePusher);
        mLivePushFragment.setStateListener(mStateListener);
        mLivePushFragment.setLiveInfoBean(liveInfoBeanData);
        SharedPreferences sharedPreferences = getSharedPreferences(Config.SP_USER_MANAGER, Context.MODE_PRIVATE);
        mLivePushFragment.setRealName(sharedPreferences.getString("realName", ""));

        initViewPager();
        mScaleDetector = new ScaleGestureDetector(getApplicationContext(), mScaleGestureDetector);
        mDetector = new GestureDetector(getApplicationContext(), mGestureDetector);
        mNetWork = NetWorkUtils.getAPNType(this);

    }

    public void initView() {
        mPreviewView = (SurfaceView) findViewById(R.id.preview_view);
        mPreviewView.getHolder().addCallback(mCallback);

        if (NetUtils.getAPNType(this) != 1 && NetUtils.getAPNType(this) != 0) {
            UIUtils.toastLongMessage("当前非wifi环境,请注意流量");
        }
    }

    private void initViewPager() {
        mViewPager = (ViewPager) findViewById(R.id.tv_pager);
//        mFragmentList.add(mPushTextStatsFragment);
        mFragmentList.add(mLivePushFragment);
//        mFragmentList.add(mPushDiagramStatsFragment);
        mFragmentAdapter = new FragmentAdapter(this.getSupportFragmentManager(), mFragmentList);
        mViewPager.setAdapter(mFragmentAdapter);
//        mViewPager.setCurrentItem(1);
        mViewPager.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
//                if(((ViewPager)view).getCurrentItem() == 1) {
                if (motionEvent.getPointerCount() >= 2 && mScaleDetector != null) {
                    mScaleDetector.onTouchEvent(motionEvent);
                } else if (motionEvent.getPointerCount() == 1 && mDetector != null) {
                    mDetector.onTouchEvent(motionEvent);
                }
//                }
                return false;
            }
        });
    }

    private void setOrientation(int orientation) {
        if (orientation == ORIENTATION_PORTRAIT.ordinal()) {
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        } else if (orientation == ORIENTATION_LANDSCAPE_HOME_RIGHT.ordinal()) {
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        } else if (orientation == ORIENTATION_LANDSCAPE_HOME_LEFT.ordinal()) {
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
        }
    }

    private GestureDetector.OnGestureListener mGestureDetector = new GestureDetector.OnGestureListener() {
        @Override
        public boolean onDown(MotionEvent motionEvent) {
            return false;
        }

        @Override
        public void onShowPress(MotionEvent motionEvent) {

        }

        @Override
        public boolean onSingleTapUp(MotionEvent motionEvent) {
            if (mPreviewView.getWidth() > 0 && mPreviewView.getHeight() > 0) {
                float x = motionEvent.getX() / mPreviewView.getWidth();
                float y = motionEvent.getY() / mPreviewView.getHeight();
                try {
                    mAlivcLivePusher.focusCameraAtAdjustedPoint(x, y, true);
                } catch (IllegalStateException e) {

                }
            }
            return true;
        }

        @Override
        public boolean onScroll(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) {
            return false;
        }

        @Override
        public void onLongPress(MotionEvent motionEvent) {

        }

        @Override
        public boolean onFling(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) {
            if (motionEvent == null || motionEvent1 == null) {
                return false;
            }
            if (motionEvent.getX() - motionEvent1.getX() > FLING_MIN_DISTANCE
                    && Math.abs(v) > FLING_MIN_VELOCITY) {
                // Fling left
            } else if (motionEvent1.getX() - motionEvent.getX() > FLING_MIN_DISTANCE
                    && Math.abs(v) > FLING_MIN_VELOCITY) {
                // Fling right
            }
            return false;
        }
    };

    private float scaleFactor = 1.0f;
    private ScaleGestureDetector.OnScaleGestureListener mScaleGestureDetector = new ScaleGestureDetector.OnScaleGestureListener() {
        @Override
        public boolean onScale(ScaleGestureDetector scaleGestureDetector) {
            if (scaleGestureDetector.getScaleFactor() > 1) {
                scaleFactor += 0.5;
            } else {
                scaleFactor -= 2;
            }
            if (scaleFactor <= 1) {
                scaleFactor = 1;
            }
            try {
                if (scaleFactor >= mAlivcLivePusher.getMaxZoom()) {
                    scaleFactor = mAlivcLivePusher.getMaxZoom();
                }
                mAlivcLivePusher.setZoom((int) scaleFactor);

            } catch (IllegalStateException e) {

            }
            return false;
        }

        @Override
        public boolean onScaleBegin(ScaleGestureDetector scaleGestureDetector) {
            return true;
        }

        @Override
        public void onScaleEnd(ScaleGestureDetector scaleGestureDetector) {

        }
    };

    SurfaceHolder.Callback mCallback = new SurfaceHolder.Callback() {
        @Override
        public void surfaceCreated(SurfaceHolder surfaceHolder) {
            if (mSurfaceStatus == SurfaceStatus.UNINITED) {
                mSurfaceStatus = SurfaceStatus.CREATED;
                if (mAlivcLivePusher != null) {
                    try {
                        if (mAsync) {
                            mAlivcLivePusher.startPreviewAysnc(mPreviewView);
                        } else {
                            mAlivcLivePusher.startPreview(mPreviewView);
                        }
                        if (mAlivcLivePushConfig.isExternMainStream()) {
                            startYUV(getApplicationContext());
                        }
                    } catch (IllegalArgumentException e) {
                        e.toString();
                    } catch (IllegalStateException e) {
                        e.toString();
                    }
                }
            } else if (mSurfaceStatus == SurfaceStatus.DESTROYED) {
                mSurfaceStatus = SurfaceStatus.RECREATED;
            }
        }

        @Override
        public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
            mSurfaceStatus = SurfaceStatus.CHANGED;
            if (mLivePushFragment != null) {
                mLivePushFragment.setSurfaceView(mPreviewView);
            }
        }

        @Override
        public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
            mSurfaceStatus = SurfaceStatus.DESTROYED;
        }
    };

    public static void startActivity(Activity activity, JsonsRootBean liveInfoBean, AlivcLivePushConfig alivcLivePushConfig, String url, boolean async, boolean audioOnly, boolean videoOnly, AlivcPreviewOrientationEnum orientation, int cameraId, boolean isFlash, String authTime, String privacyKey, boolean mixExtern, boolean mixMain) {
        Intent intent = new Intent(activity, LivePushActivity.class);
        Bundle bundle = new Bundle();
        bundle.putSerializable(AlivcLivePushConfig.CONFIG, alivcLivePushConfig);
        bundle.putSerializable("liveInfo", liveInfoBean);
        bundle.putString(URL_KEY, url);
        bundle.putBoolean(ASYNC_KEY, async);
        bundle.putBoolean(AUDIO_ONLY_KEY, audioOnly);
        bundle.putBoolean(VIDEO_ONLY_KEY, videoOnly);
        bundle.putInt(ORIENTATION_KEY, orientation.ordinal());
        bundle.putInt(CAMERA_ID, cameraId);
        bundle.putBoolean(FLASH_ON, isFlash);
        bundle.putString(AUTH_TIME, authTime);
        bundle.putString(PRIVACY_KEY, privacyKey);
        bundle.putBoolean(MIX_EXTERN, mixExtern);
        bundle.putBoolean(MIX_MAIN, mixMain);
        intent.putExtras(bundle);
        activity.startActivityForResult(intent, REQ_CODE_PUSH);
    }

    @Override
    protected void onResume() {
        super.onResume();
        ShareUtils.putBoolean("livePasue", true);
        if (mAlivcLivePusher != null) {
            try {
                if (!isPause) {
                    if (mAsync) {
                        mAlivcLivePusher.resumeAsync();
                    } else {
                        mAlivcLivePusher.resume();
                    }
                }
            } catch (IllegalStateException e) {
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (mAlivcLivePusher != null) {
            try {
                if (mAlivcLivePusher != null/*.isPushing()*/) {//退出后台也走这个
                    if (ShareUtils.getBoolean("livePasue", true)) {
                        mAlivcLivePusher.pause();//这个时候不调暂停接口
                        ShareUtils.putBoolean("livePasue", true);
                    }
//                    mAlivcLivePusher.pause();//这个时候不调暂停接口
                }
            } catch (IllegalStateException e) {
                e.printStackTrace();
            }
        }
//        if(mHandler != null) {
//            mHandler.removeCallbacks(mRunnable);
//        }
    }

    @Override
    protected void onDestroy() {
        EventBus.getDefault().unregister(this);
        videoThreadOn = false;
        audioThreadOn = false;
        if (mAlivcLivePusher != null) {
            try {
                mAlivcLivePusher.destroy();
            } catch (IllegalStateException e) {
                e.printStackTrace();
            }
        }
//        if(mHandler != null) {
//            mHandler.removeCallbacks(mRunnable);
//            mHandler = null;
//        }
//        unregisterReceiver(mChangedReceiver);
        mFragmentList = null;
        mPreviewView = null;
        mViewPager = null;
        mFragmentAdapter = null;
        mDetector = null;
        mScaleDetector = null;
        mLivePushFragment = null;
        mAlivcLivePushConfig = null;

        mAlivcLivePusher = null;

//        mHandler = null;
        alivcLivePushStatsInfo = null;
        super.onDestroy();
    }

    public class FragmentAdapter extends FragmentPagerAdapter {

        List<Fragment> fragmentList = new ArrayList<>();

        public FragmentAdapter(FragmentManager fm, List<Fragment> fragmentList) {
            super(fm);
            this.fragmentList = fragmentList;
        }

        @Override
        public Fragment getItem(int position) {
            return fragmentList.get(position);
        }

        @Override
        public int getCount() {
            return fragmentList.size();
        }

    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        int rotation = getWindowManager().getDefaultDisplay().getRotation();
        AlivcPreviewOrientationEnum orientationEnum;
        if (mAlivcLivePusher != null) {
            switch (rotation) {
                case Surface.ROTATION_0:
                    orientationEnum = ORIENTATION_PORTRAIT;
                    break;
                case Surface.ROTATION_90:
                    orientationEnum = ORIENTATION_LANDSCAPE_HOME_RIGHT;
                    break;
                case Surface.ROTATION_270:
                    orientationEnum = ORIENTATION_LANDSCAPE_HOME_LEFT;
                    break;
                default:
                    orientationEnum = ORIENTATION_PORTRAIT;
                    break;
            }
            try {
                mAlivcLivePusher.setPreviewOrientation(orientationEnum);
            } catch (IllegalStateException e) {

            }
        }
    }

    public AlivcLivePusher getLivePusher() {
        return this.mAlivcLivePusher;
    }

    public SurfaceView getPreviewView() {
        return this.mPreviewView;
    }

    private void showDialog(Context context, String message) {
        AlertDialog.Builder dialog = new AlertDialog.Builder(context);
        dialog.setTitle(getString(R.string.dialog_title));
        dialog.setMessage(message);
        dialog.setNegativeButton(getString(R.string.ok), new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                finish();
            }
        });
        dialog.show();
    }

    private Runnable mRunnable = new Runnable() {
        @Override
        public void run() {
            LogUtil.d(TAG, "====== mRunnable run ======");

            new AsyncTask<AlivcLivePushStatsInfo, Void, AlivcLivePushStatsInfo>() {
                @Override
                protected AlivcLivePushStatsInfo doInBackground(AlivcLivePushStatsInfo... alivcLivePushStatsInfos) {
                    try {
                        alivcLivePushStatsInfo = mAlivcLivePusher.getLivePushStatsInfo();
                    } catch (IllegalStateException e) {

                    }
                    return alivcLivePushStatsInfo;
                }

                @Override
                protected void onPostExecute(AlivcLivePushStatsInfo alivcLivePushStatsInfo) {
                    super.onPostExecute(alivcLivePushStatsInfo);
//                    if(mPushTextStatsFragment != null && mViewPager.getCurrentItem() == 0) {
//                        mPushTextStatsFragment.updateValue(alivcLivePushStatsInfo);
//                    } else if (mPushDiagramStatsFragment != null && mViewPager.getCurrentItem() == 2) {
//                        mPushDiagramStatsFragment.updateValue(alivcLivePushStatsInfo);
//                    }
////                    mHandler.postDelayed(mRunnable, REFRESH_INTERVAL);
                }
            }.execute();
        }
    };

    public interface PauseState {
        void updatePause(boolean state);
    }

    private PauseState mStateListener = new PauseState() {
        @Override
        public void updatePause(boolean state) {
            isPause = state;
        }
    };

    class ConnectivityChangedReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {

            if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) {

                if (mNetWork != NetWorkUtils.getAPNType(context)) {
                    mNetWork = NetWorkUtils.getAPNType(context);
                    if (mAlivcLivePusher != null) {
                        if (mAlivcLivePusher.isPushing()) {
                            try {
                                mAlivcLivePusher.reconnectPushAsync(null);
                            } catch (IllegalStateException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            }

        }
    }

    public void startYUV(final Context context) {
        new ScheduledThreadPoolExecutor(1, new ThreadFactory() {
            private AtomicInteger atoInteger = new AtomicInteger(0);

            public Thread newThread(Runnable r) {
                Thread t = new Thread(r);
                t.setName("LivePushActivity-readYUV-Thread" + atoInteger.getAndIncrement());
                return t;
            }
        }).execute(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                videoThreadOn = true;
                byte[] yuv;
                InputStream myInput = null;
                try {
                    File f = new File(Environment.getExternalStorageDirectory().getPath() + File.separator + "alivc_resource/capture0.yuv");
                    myInput = new FileInputStream(f);
                    byte[] buffer = new byte[1280 * 720 * 3 / 2];
                    int length = myInput.read(buffer);
                    //发数据
                    while (length > 0 && videoThreadOn) {
                        mAlivcLivePusher.inputStreamVideoData(buffer, 720, 1280, 720, 1280 * 720 * 3 / 2, System.nanoTime() / 1000, 0);
                        try {
                            Thread.sleep(40);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        //发数据
                        length = myInput.read(buffer);
                        if (length <= 0) {
                            myInput.close();
                            myInput = new FileInputStream(f);
                            length = myInput.read(buffer);
                        }
                    }
                    myInput.close();
                    videoThreadOn = false;
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            quitThisLive();
        }
        return super.onKeyDown(keyCode, event);
    }

    private void quitThisLive() {
        new CommomLiveDialog(this, R.style.ActionSheetDialogStyle, "", new CommomLiveDialog.OnCloseListener() {
            @Override
            public void onClick(Dialog dialog, boolean confirm) {
                if (confirm) {
                    if (NetUtils.getAPNType(LivePushActivity.this) == 0) {
//                        mLivePushFragment.stopLivePusher();//无网只关闭直播
                        finish();
                    } else {
                        mLivePushFragment.exitLive();
                    }
                } else {
                    dialog.dismiss();
                }
            }
        }).show();
    }

布局文件,使用SurfaceView上面贴一个ViewPager,用来写自定义布局:


```java
<RelativeLayout 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:keepScreenOn="true"
    tools:ignore="MissingDefaultResource">
    <SurfaceView
        android:id="@+id/preview_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <android.support.v4.view.ViewPager
        android:id="@+id/tv_pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        >
    </android.support.v4.view.ViewPager>

</RelativeLayout>

5.编写自己的推流逻辑,重画UI


```java
public class LivePushFragment extends Fragment implements Runnable {
    public static final String TAG = "LivePushFragment";

    private static final String URL_KEY = "url_key";
    private static final String ASYNC_KEY = "async_key";
    private static final String AUDIO_ONLY_KEY = "audio_only_key";
    private static final String VIDEO_ONLY_KEY = "video_only_key";
    private static final String QUALITY_MODE_KEY = "quality_mode_key";
    private static final String CAMERA_ID = "camera_id";
    private static final String FLASH_ON = "flash_on";
    private static final String AUTH_TIME = "auth_time";
    private static final String PRIVACY_KEY = "privacy_key";
    private static final String MIX_EXTERN = "mix_extern";
    private static final String MIX_MAIN = "mix_main";
    private final long REFRESH_INTERVAL = 2000;

    private Button mExit;
    private ImageView mFlash;
    private ImageView mCamera;


    private AlivcLivePusher mAlivcLivePusher = null;
    private String mPushUrl = null;
    private SurfaceView mSurfaceView = null;
    private boolean mAsync = false;

    private boolean mAudio = false;
    private boolean mVideoOnly = false;
    private boolean isPushing = false;
    private Handler mHandler = new Handler();

    private LivePushActivity.PauseState mStateListener = null;
    private int mCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT;
    private boolean isFlash = false;
    private boolean mMixExtern = false;
    private boolean mMixMain = false;
    private boolean flashState = true;

    private int snapshotCount = 0;

    private int mQualityMode = 0;


    private TextView captureNumTv, captureThemeTv, delayTitleTv, liveStartNameTv, lookViewerTv;//人数和主题
    private LinearLayout delayTimell;
    private ImageView headerIv;
    private GridView viewerGv;
    private ImageView addViewerIv;
    private CircleImageView viewer1, viewer2, viewer3;


    ScheduledExecutorService mExecutorService = new ScheduledThreadPoolExecutor(5,
            new BasicThreadFactory.Builder().namingPattern("example-schedule-pool-%d").daemon(true).build());

    private boolean audioThreadOn = false;


    private String mAuthString = "?auth_key=%1$d-%2$d-%3$d-%4$s";
    private String mMd5String = "%1$s-%2$d-%3$d-%4$d-%5$s";
    private String mTempUrl = null;
    private String mAuthTime = "";
    private String mPrivacyKey = "";

    private Timer timer;


    Vector<Integer> mDynamicals = new Vector<>();
    private List<SelectPersonContainerBean.UserListBean> persons = new ArrayList<SelectPersonContainerBean.UserListBean>();
    private List<SelectPersonContainerBean.UserListBean> tempPersons = new ArrayList<SelectPersonContainerBean.UserListBean>();
    private JsonsRootBean liveInfoBean;
    private String realName = "";

    private JsonsRootBean jsonsRootBean = null;

    public void setRealName(String realName) {
        this.realName = realName;
    }

    public void setLiveInfoBean(JsonsRootBean liveInfoBean) {
        this.liveInfoBean = liveInfoBean;
    }

    public static LivePushFragment newInstance(String url, boolean async, boolean mAudio, boolean mVideoOnly, int cameraId, boolean isFlash, int mode, String authTime, String privacyKey, boolean mixExtern, boolean mixMain) {
        LivePushFragment livePushFragment = new LivePushFragment();
        Bundle bundle = new Bundle();
        bundle.putString(URL_KEY, url);
        bundle.putBoolean(ASYNC_KEY, async);
        bundle.putBoolean(AUDIO_ONLY_KEY, mAudio);
        bundle.putBoolean(VIDEO_ONLY_KEY, mVideoOnly);
        bundle.putInt(QUALITY_MODE_KEY, mode);
        bundle.putInt(CAMERA_ID, cameraId);
        bundle.putBoolean(FLASH_ON, isFlash);
        bundle.putString(AUTH_TIME, authTime);
        bundle.putString(PRIVACY_KEY, privacyKey);
        bundle.putBoolean(MIX_EXTERN, mixExtern);
        bundle.putBoolean(MIX_MAIN, mixMain);
        livePushFragment.setArguments(bundle);
        return livePushFragment;
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mPushUrl = getArguments().getString(URL_KEY);
            mTempUrl = mPushUrl;
            mAsync = getArguments().getBoolean(ASYNC_KEY, false);
            mAudio = getArguments().getBoolean(AUDIO_ONLY_KEY, false);
            mVideoOnly = getArguments().getBoolean(VIDEO_ONLY_KEY, false);
            mCameraId = getArguments().getInt(CAMERA_ID);
            isFlash = getArguments().getBoolean(FLASH_ON, false);
            mMixExtern = getArguments().getBoolean(MIX_EXTERN, false);
            mMixMain = getArguments().getBoolean(MIX_MAIN, false);
            mQualityMode = getArguments().getInt(QUALITY_MODE_KEY);
            mAuthTime = getArguments().getString(AUTH_TIME);
            mPrivacyKey = getArguments().getString(PRIVACY_KEY);
            flashState = isFlash;
        }
        if (mAlivcLivePusher != null) {
            mAlivcLivePusher.setLivePushInfoListener(mPushInfoListener);
            mAlivcLivePusher.setLivePushErrorListener(mPushErrorListener);
            mAlivcLivePusher.setLivePushNetworkListener(mPushNetworkListener);
            mAlivcLivePusher.setLivePushBGMListener(mPushBGMListener);
            isPushing = mAlivcLivePusher.isPushing();
        }

    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.push_fragment, container, false);
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

  
        mFlash.setVisibility(mAudio ? View.GONE : View.VISIBLE);
        mCamera.setVisibility(mAudio ? View.GONE : View.VISIBLE);
        mFlash.setClickable(mCameraId == CAMERA_TYPE_BACK.getCameraId() ? false : true);//闪光灯根据摄像头切换
        timerStart();//直播到计时开始计时


    }

    private void quitThisLive() {
        new CommomLiveDialog(getContext(), R.style.ActionSheetDialogStyle, "", new CommomLiveDialog.OnCloseListener() {
            @Override
            public void onClick(Dialog dialog, boolean confirm) {
                if (confirm) {
                    if (getActivity() != null) {
                        if (NetUtils.getAPNType(getActivity()) == 0) {
//                        stopLivePusher();//无网只关闭直播
                            getActivity().finish();
                        } else {
                            exitLive();
                        }
                    }
                } else {
                    dialog.dismiss();
                }
            }
        }).show();
    }

  
    //非正常操作退出的
//    public void exitLiveError(final String msg) {
//        if (liveInfoBean != null) {
//            String url = App.getInstance().getIP() + Config.CREATE_LIVE_DELETE + "?userId=" + App.getInstance().getUserId() + "&liveId=" + liveInfoBean.getId();
//            App.getInstance().getRequestQueue().add(new HeaderStringRequest(Request.Method.POST, url, new CustomResonse<String>() {
//                @Override
//                public void onCustomResponse(String s) {
//                    LogUtils.i(s);
//                    ResponseBean responseBean = JsonParseUtil.getBean(s, ResponseBean.class);
//                    if (responseBean.getCode() == 200) {
//                        UIUtils.toastLongMessage(msg);
//                        getActivity().finish();
//                    }
//                }
//            }, new CustomErrorListener() {
//                @Override
//                public void onCustomErrorResponse(VolleyError volleyError) {
//
//                }
//            }));
//        }
//    }

    public void stopLivePusher() {
        if (timer1 != null) {
            timerCancel();
        }
        if (mAlivcLivePusher != null) {
            mAlivcLivePusher.stopPush();
            stopPcm();
            //停止推流
            if (mStateListener != null) {
                mStateListener.updatePause(false);
            }
        }
        getActivity().finish();
    }


    View.OnClickListener onClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            final int id = view.getId();

            if (mAlivcLivePusher == null) {
                if (getActivity() != null) {
                    mAlivcLivePusher = ((LivePushActivity) getActivity()).getLivePusher();
                }

                if (mAlivcLivePusher == null) {
                    return;
                }
            }

            mExecutorService.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        switch (id) {
                            case R.id.flashButton:
                                //闪光灯
                                mAlivcLivePusher.setFlash(!mFlash.isSelected());
                                flashState = !mFlash.isSelected();
                                mFlash.post(new Runnable() {
                                    @Override
                                    public void run() {
                                        mFlash.setSelected(!mFlash.isSelected());
                                    }
                                });
                                break;
                            case R.id.switchFacingButton:
                                //切换摄像头
                                if (mCameraId == CAMERA_TYPE_FRONT.getCameraId()) {
                                    mCameraId = CAMERA_TYPE_BACK.getCameraId();
                                } else {
                                    mCameraId = CAMERA_TYPE_FRONT.getCameraId();
                                }
                                mAlivcLivePusher.switchCamera();
                                mFlash.post(new Runnable() {
                                    @Override
                                    public void run() {
                                        mFlash.setClickable(mCameraId == CAMERA_TYPE_BACK.getCameraId() ? false : true);
                                        if (mCameraId == CAMERA_TYPE_BACK.getCameraId()) {
                                            mFlash.setSelected(false);
                                        } else {
                                            mFlash.setSelected(flashState);
                                        }
                                    }
                                });
                                break;
                            default:
                                break;
                        }
                    } catch (IllegalArgumentException e) {
                        showDialog(e.getMessage());
                        e.printStackTrace();
                    } catch (IllegalStateException e) {
                        showDialog(e.getMessage());
                        e.printStackTrace();
                    }
                }
            });

        }
    };


    public void setAlivcLivePusher(AlivcLivePusher alivcLivePusher) {
        this.mAlivcLivePusher = alivcLivePusher;
    }

    public void setStateListener(LivePushActivity.PauseState listener) {
        this.mStateListener = listener;
    }

    public void setSurfaceView(SurfaceView surfaceView) {
        this.mSurfaceView = surfaceView;
    }


    AlivcLivePushInfoListener mPushInfoListener = new AlivcLivePushInfoListener() {
        @Override
        public void onPreviewStarted(AlivcLivePusher pusher) {
//            showToast(getString(R.string.start_preview));//开始预览
        }

        @Override
        public void onPreviewStoped(AlivcLivePusher pusher) {
            showToast(getString(R.string.stop_preview));
        }

        @Override
        public void onPushStarted(AlivcLivePusher pusher) {
            showToast(getString(R.string.start_push));
            initTimer(0, 6000);
            initTimer(1, 6000 * 10);
        }

        @Override
        public void onFirstAVFramePushed(AlivcLivePusher pusher) {
        }

        @Override
        public void onPushPauesed(AlivcLivePusher pusher) {//跳页面以后走这个
//            showToast(getString(R.string.pause_push));
            stopTimer();//停止更新UI
        }

        @Override
        public void onPushResumed(AlivcLivePusher pusher) {//恢复
//            showToast(getString(R.string.resume_push));
            initTimer(0, 6000);
            initTimer(1, 6000 * 10);
        }

        @Override
        public void onPushStoped(AlivcLivePusher pusher) {
//            showToast(getString(R.string.stop_push));
            stopTimer();
        }

        /**
         * 推流重启通知
         *
         * @param pusher AlivcLivePusher实例
         */
        @Override
        public void onPushRestarted(AlivcLivePusher pusher) {
//            showToast(getString(R.string.restart_success));
        }

        @Override
        public void onFirstFramePreviewed(AlivcLivePusher pusher) {
//            showToast(getString(R.string.first_frame));
        }

        @Override
        public void onDropFrame(AlivcLivePusher pusher, int countBef, int countAft) {
//            showToast(getString(R.string.drop_frame) + ", 丢帧前:" + countBef + ", 丢帧后:" + countAft);
        }

        @Override
        public void onAdjustBitRate(AlivcLivePusher pusher, int curBr, int targetBr) {
//            showToast(getString(R.string.adjust_bitrate) + ", 当前码率:" + curBr + "Kps, 目标码率:" + targetBr + "Kps");
        }

        @Override
        public void onAdjustFps(AlivcLivePusher pusher, int curFps, int targetFps) {
//            showToast(getString(R.string.adjust_fps) + ", 当前帧率:" + curFps + ", 目标帧率:" + targetFps);
        }
    };

    AlivcLivePushErrorListener mPushErrorListener = new AlivcLivePushErrorListener() {

        @Override
        public void onSystemError(AlivcLivePusher livePusher, AlivcLivePushError error) {
//            showDialog(getString(R.string.system_error) + error.toString());
        }

        @Override
        public void onSDKError(AlivcLivePusher livePusher, AlivcLivePushError error) {
            if (error != null) {
//                showDialog(getString(R.string.sdk_error) + error.toString());
                if (mAlivcLivePusher != null) {
                    //启动重连
                    mAlivcLivePusher.setLivePushNetworkListener(mPushNetworkListener);
                    isPushing = mAlivcLivePusher.isPushing();
                }

            }
        }
    };

    AlivcLivePushNetworkListener mPushNetworkListener = new AlivcLivePushNetworkListener() {
        @Override
        public void onNetworkPoor(AlivcLivePusher pusher) {
            showNetWorkDialog(getString(R.string.network_poor), 0);
//            mAlivcLivePusher.reconnectPushAsync(null);
        }

        @Override
        public void onNetworkRecovery(AlivcLivePusher pusher) {
            showToast(getString(R.string.network_recovery));
        }

        @Override
        public void onReconnectStart(AlivcLivePusher pusher) {
            if (NetUtils.getAPNType(getActivity()) == 0) {
//                UIUtils.toastLongMessage("当前非wifi环境,请注意流量");
                stopTimer();
                showDialog(getString(R.string.tip_unavaild_net));
            } else {
//                initTimer();
                showToastShort(getString(R.string.reconnect_start));
            }
        }

        @Override
        public void onReconnectFail(AlivcLivePusher pusher) {
            if (NetUtils.getAPNType(getActivity()) == 0) {
                stopTimer();
//                UIUtils.toastLongMessage("当前非wifi环境,请注意流量");
                showDialog(getString(R.string.tip_unavaild_net));
            } else {
                showDialog(getString(R.string.reconnect_fail));
            }
        }

        @Override
        public void onReconnectSucceed(AlivcLivePusher pusher) {
            showToast(getString(R.string.reconnect_success));
        }

        @Override
        public void onSendDataTimeout(AlivcLivePusher pusher) {
            showDialog(getString(R.string.senddata_timeout));
        }

        @Override
        public void onConnectFail(AlivcLivePusher pusher) {
            showDialog(getString(R.string.connect_fail));
        }

        @Override
        public void onConnectionLost(AlivcLivePusher pusher) {
//            showToast("推流已断开");
//            exitLiveError("推流已断开");
        }

        @Override
        public String onPushURLAuthenticationOverdue(AlivcLivePusher pusher) {
            showDialog("流即将过期,请更换url");
            return getAuthString(mAuthTime);
        }

        @Override
        public void onSendMessage(AlivcLivePusher pusher) {
            showToast(getString(R.string.send_message));
        }

        @Override
        public void onPacketsLost(AlivcLivePusher pusher) {
//            showToast("推流丢包通知");
//            exitLiveError("丢包了请重进");
        }
    };

    private AlivcLivePushBGMListener mPushBGMListener = new AlivcLivePushBGMListener() {
        @Override
        public void onStarted() {

        }

        @Override
        public void onStoped() {

        }

        @Override
        public void onPaused() {

        }

        @Override
        public void onResumed() {

        }

        @Override
        public void onProgress(final long progress, final long duration) {
            getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
//                    if(mMusicDialog != null) {
//                        mMusicDialog.updateProgress(progress, duration);
//                    }
                }
            });
        }

        @Override
        public void onCompleted() {

        }

        @Override
        public void onDownloadTimeout() {

        }

        @Override
        public void onOpenFailed() {
            showDialog(getString(R.string.bgm_open_failed));
        }
    };

    @Override
    public void onDestroy() {
        //stopPcm();
        //stopYUV();
        super.onDestroy();
        stopTimer();
        if (mExecutorService != null && !mExecutorService.isShutdown()) {
            mExecutorService.shutdown();
        }
    }

    private void showToast(final String text) {
        if (getActivity() == null || text == null) {
            return;
        }
        Handler handler = new Handler(Looper.getMainLooper());
        handler.post(new Runnable() {
            @Override
            public void run() {
                if (getActivity() != null) {
                    Toast toast = Toast.makeText(getActivity(), text, Toast.LENGTH_SHORT);
                    toast.setGravity(Gravity.CENTER, 0, 0);
                    toast.show();
                }
            }
        });
    }

    private void showToastShort(final String text) {
        if (getActivity() == null || text == null) {
            return;
        }
        Handler handler = new Handler(Looper.getMainLooper());
        handler.post(new Runnable() {
            @Override
            public void run() {
                if (getActivity() != null) {
                    Toast toast = Toast.makeText(getActivity(), text, Toast.LENGTH_SHORT);
                    toast.setGravity(Gravity.CENTER, 0, 0);
                    toast.show();
                }
            }
        });
    }

    private void showDialog(final String message) {
        if (getActivity() == null || message == null) {
            return;
        }
        Handler handler = new Handler(Looper.getMainLooper());
        handler.post(new Runnable() {
            @Override
            public void run() {
                if (getActivity() != null) {
                    if (mAlivcLivePusher != null) {
                        mAlivcLivePusher.reconnectPushAsync(null);
                    }
//                    Toast.makeText(getActivity(),message,Toast.LENGTH_LONG).show();
                    Toast toast = Toast.makeText(getActivity(), message, Toast.LENGTH_SHORT);
                    toast.setGravity(Gravity.CENTER, 0, 0);
                    toast.show();
                }

            }
        });
    }

    private void showNetWorkDialog(final String message, int index) {
        if (getActivity() == null || message == null) {
            return;
        }
        Handler handler = new Handler(Looper.getMainLooper());
        handler.post(new Runnable() {
            @Override
            public void run() {
                if (getActivity() != null) {
                    mAlivcLivePusher.reconnectPushAsync(null);
//                    Toast.makeText(getActivity(),message,Toast.LENGTH_LONG).show();
                    Toast toast = Toast.makeText(getActivity(), message, Toast.LENGTH_SHORT);
                    toast.setGravity(Gravity.CENTER, 0, 0);
                    toast.show();
                }
            }
        });
    }

    @Override
    public void run() {
//        if(mIsPushing != null && mAlivcLivePusher != null) {
//            try {
//                isPushing = mAlivcLivePusher.isNetworkPushing();
//            } catch (IllegalStateException e) {
//                e.printStackTrace();
//            }
//            AlivcLivePushError error = mAlivcLivePusher.getLastError();
//            if(!error.equals(AlivcLivePushError.ALIVC_COMMON_RETURN_SUCCESS)) {
//                mIsPushing.setText(String.valueOf(isPushing)+", error code : "+error.getCode());
//            } else {
//                mIsPushing.setText(String.valueOf(isPushing));
//            }
//        }
//        mHandler.postDelayed(this, REFRESH_INTERVAL);

    }

    @Override
    public void onResume() {
        super.onResume();
        mHandler.post(this);
    }

    @Override
    public void onPause() {
        super.onPause();
        mHandler.removeCallbacks(this);
    }


    private String getMD5(String string) {

        byte[] hash;

        try {
            hash = MessageDigest.getInstance("MD5").digest(string.getBytes("UTF-8"));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return null;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return null;
        }

        StringBuilder hex = new StringBuilder(hash.length * 2);
        for (byte b : hash) {
            if ((b & 0xFF) < 0x10) {
                hex.append("0");
            }
            hex.append(Integer.toHexString(b & 0xFF));
        }

        return hex.toString();
    }

    private String getUri(String url) {
        String result = "";
        String temp = url.substring(7);
        if (temp != null && !temp.isEmpty()) {
            result = temp.substring(temp.indexOf("/"));
        }
        return result;
    }


    private String getAuthString(String time) {
        if (!time.isEmpty() && !mPrivacyKey.isEmpty()) {
            long tempTime = (System.currentTimeMillis() + Integer.valueOf(time)) / 1000;
            String tempprivacyKey = String.format(mMd5String, getUri(mPushUrl), tempTime, 0, 0, mPrivacyKey);
            String auth = String.format(mAuthString, tempTime, 0, 0, getMD5(tempprivacyKey));
            mTempUrl = mPushUrl + auth;
        } else {
            mTempUrl = mPushUrl;
        }
        return mTempUrl;
    }

    private void startPCM(final Context context) {
        new ScheduledThreadPoolExecutor(1, new ThreadFactory() {
            private AtomicInteger atoInteger = new AtomicInteger(0);

            @Override
            public Thread newThread(Runnable r) {
                Thread t = new Thread(r);
                t.setName("LivePushActivity-readPCM-Thread" + atoInteger.getAndIncrement());
                return t;
            }
        }).execute(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                audioThreadOn = true;
                byte[] pcm;
                int allSended = 0;
                int sizePerSecond = 44100 * 2;
                InputStream myInput = null;
                OutputStream myOutput = null;
                boolean reUse = false;
                long startPts = System.nanoTime() / 1000;
                try {
                    File f = new File("/sdcard/alivc_resource/441.pcm");
                    myInput = new FileInputStream(f);
                    byte[] buffer = new byte[2048];
                    int length = myInput.read(buffer, 0, 2048);
                    while (length > 0 && audioThreadOn) {
                        long pts = System.nanoTime() / 1000;
                        mAlivcLivePusher.inputStreamAudioData(buffer, length, 44100, 1, pts);
                        allSended += length;
                        if ((allSended * 1000000L / sizePerSecond - 50000) > (pts - startPts)) {
                            try {
                                Thread.sleep(45);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        length = myInput.read(buffer);
                        if (length < 2048) {
                            myInput.close();
                            myInput = new FileInputStream(f);
                            length = myInput.read(buffer);
                        }
                        try {
                            Thread.sleep(3);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    myInput.close();
                    audioThreadOn = false;
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    private void stopPcm() {
        audioThreadOn = false;
    }

    /**
     * 倒数计时器
     */
    private CountDownTimer timer1 = new CountDownTimer(3000, 1000) {
        /**
         * 固定间隔被调用,就是每隔countDownInterval会回调一次方法onTick
         * @param millisUntilFinished
         */
        @Override
        public void onTick(long millisUntilFinished) {
            Log.e("captureActivity===", delayTitleTv.getText().toString());
            int index1 = Integer.parseInt(delayTitleTv.getText().toString());
            if (index1 != 1) {
                delayTitleTv.setText(index1 - 1 + "");
            }
        }

        /**
         * 倒计时完成时被调用
         */
        @Override
        public void onFinish() {
//            delayTitleTv.setVisibility(View.GONE);
            delayTimell.setVisibility(View.GONE);
            startLive(true);//开始推流
            if (timer1 != null) {
                timerCancel();//取消
            }
        }
    };

    public void startLive(boolean isStart) {
        final boolean isPush = isStart;
        if (isPush) {
            if (mAsync) {
                mAlivcLivePusher.startPushAysnc(getAuthString(mAuthTime));
            } else {
                mAlivcLivePusher.startPush(getAuthString(mAuthTime));
            }
            if (mMixExtern) {
                //startMixPCM(getActivity());
            } else if (mMixMain) {
                startPCM(getActivity());
            }
            if (liveInfoBean != null) {
                sendViewerNotify();
            }
        } else {
            if (mAlivcLivePusher != null) {
                mAlivcLivePusher.stopPush();
                stopPcm();
                //停止推流
                if (mStateListener != null) {
                    mStateListener.updatePause(false);
                }
            }
        }
    }

    /**
     * 取消倒计时
     */
    public void timerCancel() {
        timer1.cancel();
        timer1 = null;
    }

    /**
     * 开始倒计时
     */
    public void timerStart() {
        timer1.start();
    }

 

    // 停止定时任务
    private void stopTimer() {
        if (timer != null) {
            timer.cancel();
            // 一定设置为null,否则定时器不会被回收
            timer = null;
        }
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == Activity.RESULT_OK) {
            List<SelectPersonContainerBean.UserListBean> ids = (List<SelectPersonContainerBean.UserListBean>) data.getSerializableExtra("ids");
//            LogUtils.w(ids);
            if (requestCode == 1) {
                if (ids.size() > 0) {
                    if (persons.size() != tempPersons.size()) {
                        int index = persons.size() - tempPersons.size();
                        if (ids.size() > index) {
                            persons.clear();
                            persons.addAll(tempPersons);
                            persons.addAll(ids);
                            addViewer(ids);
                        }
                    } else {
                        persons.clear();
                        persons.addAll(tempPersons);
                        persons.addAll(ids);
                        addViewer(ids);
                    }
                }

            }
        }
    }

    private void addViewer(List<SelectPersonContainerBean.UserListBean> ids) {
        List<String> idList = new ArrayList<>();
        for (int i = 0; i < ids.size(); i++) {
            idList.add(ids.get(i).getId());
        }
        JSONArray jsonArray = new JSONArray(idList);
        String url = App.getInstance().getIP() + Config.CREATE_LIVE_ADDUSER + "?userId=" + App.getInstance().getUserId() + "&liveId=" + liveInfoBean.getId();
        App.getInstance().getRequestQueue().add(new HeaderJSONArrayRequest(Request.Method.POST, url, jsonArray, new Response.Listener<JSONArray>() {
            @Override
            public void onResponse(JSONArray response) {
                Log.e("JSONArrayRequest", "添加成功" + response);
            }
        }, new CustomJsonArrayParseListener() {
            @Override
            public void onJsonArrayParse(String response) {
//                Log.e("JSONArrayRequest","添加成功"+response);
//                ResponseBean responseBean=JsonParseUtil.getBean(response,ResponseBean.class);
//                if(responseBean.getCode()==200){
                UIUtils.toastLongMessage("添加成功");
                Log.e("JSONArrayRequest", "添加成功");
                setPersonUnSelected();
//                }
            }

            @Override
            public void onCustomErrorResponse(VolleyError volleyError) {

            }
        }));
    }

    private void setPersonUnSelected() {
        //设置选中的人为不可选状态
//        List<SelectPersonContainerBean.UserListBean> tempPersons = new ArrayList<>();
        for (int i = 0; i < persons.size(); i++) {
            persons.get(i).setUnCheckable(true);
        }
    }

}
页面布局:


```java
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/mainLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:keepScreenOn="true"
    tools:ignore="MissingDefaultResource">

    <ImageView
        android:id="@+id/imageAutoFocusRect"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:contentDescription="@null"
        android:scaleType="fitCenter"
        android:visibility="invisible"
        app:srcCompat="@mipmap/icon_auto_focus" />

    <RelativeLayout
        android:id="@+id/topLinearLayout"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">

        <LinearLayout
            android:id="@+id/closeButton_ll"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_marginTop="20dp"
            android:layout_marginRight="13dp"
            android:background="@drawable/activity_mlive_orcle_background"
            >
            <Button
                android:id="@+id/closeButton"
                android:layout_width="18dp"
                android:layout_height="18dp"
                android:background="@mipmap/icon_close"
                android:contentDescription="@null"
                android:layout_margin="8dp"
                />
        </LinearLayout>
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_marginLeft="13dp"
            android:layout_marginTop="10dp"
            android:background="@drawable/activity_mlive_orcle_background"
            android:gravity="center_vertical"
            android:orientation="horizontal"
            android:paddingRight="20dp"

            >
    <ImageView
                android:id="@+id/live_header_iv"
                android:layout_width="50dp"
                android:layout_height="50dp"
                android:visibility="visible"/>
            <TextView
                android:id="@+id/tv_live_startname"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="5dp"
                android:textColor="@color/white"
                android:textSize="14dp" />
        </LinearLayout>

    </RelativeLayout>

    <TextView
        android:id="@+id/tv_theme_capture"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/topLinearLayout"
        android:layout_marginLeft="13dp"
        android:layout_marginTop="20dp"
        android:background="@drawable/activity_main_start_btn_push_background"
        android:paddingLeft="10dp"
        android:paddingTop="5dp"
        android:paddingRight="10dp"
        android:paddingBottom="5dp"
        android:textColor="@color/bg_toolbar"
        android:textSize="12dp" />

    <LinearLayout
        android:id="@+id/delay_time_ll"
        android:layout_width="140dp"
        android:layout_height="100dp"
        android:layout_centerInParent="true"
        android:background="@drawable/activity_main_start_btn_push_background"
        android:gravity="center"
        android:orientation="vertical">
        <TextView
            android:id="@+id/delay_time_tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:text="4"
            android:textColor="@color/warning_text"
            android:textSize="28dp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:text="直播即将开始"
            android:textColor="@color/transRed"
            android:textSize="16dp" />

    </LinearLayout>

    <LinearLayout
        android:id="@+id/functionButtonLayout_left"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentBottom="true"
        android:layout_marginLeft="13dp"
        android:layout_marginBottom="20dp"
        android:orientation="vertical">

        <TextView
            android:id="@+id/num_capture_tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:background="@drawable/activity_main_start_btn_push_background"
            android:paddingLeft="10dp"
            android:paddingTop="5dp"
            android:paddingRight="10dp"
            android:paddingBottom="5dp"
            android:textColor="@color/white"
            android:textSize="12dp" />
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:orientation="horizontal"
            >
            <GridView
                android:id="@+id/gv_viewer_inline"
                android:layout_width="126dp"
                android:layout_height="40dp"
                android:background="@color/transparent"
                android:gravity="center_vertical|right"
                android:horizontalSpacing="2dp"
                android:visibility="gone"
                />
         
            <TextView
                android:id="@+id/tv_look_viewer"
                android:layout_width="40dp"
                android:layout_height="wrap_content"
                android:text="..."
                android:gravity="center"
                android:textSize="24dp"
                android:textColor="#BBBBBB"
                android:visibility="gone"
                />
            <ImageView
                android:id="@+id/iv_add_viewer"
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:scaleType="centerInside"
                android:src="@drawable/add_group_member"
                android:background="@drawable/mlive_addviewer_background"
                android:layout_marginLeft="5dp"
                />
        </LinearLayout>

    </LinearLayout>
    <!--功能列表-->
    <LinearLayout
        android:id="@+id/functionButtonLayout"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentEnd="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentBottom="true"
        android:layout_marginRight="13dp"
        android:layout_marginBottom="20dp"
        android:orientation="horizontal">

        <LinearLayout
            android:id="@+id/flashLayout"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:orientation="vertical">

            <ImageView
                android:id="@+id/flashButton"
                android:layout_width="33dp"
                android:layout_height="33dp"
                android:layout_gravity="center_horizontal"
                android:src="@drawable/flash_selector" />

            <!--<TextView-->
            <!--android:layout_width="wrap_content"-->
            <!--android:layout_height="wrap_content"-->
            <!--android:layout_gravity="center_horizontal"-->
            <!--android:layout_marginTop="4dp"-->
            <!--android:text="补光"-->
            <!--android:textColor="@color/white" />-->

        </LinearLayout>

        <LinearLayout
            android:id="@+id/switchFacingLayout"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginLeft="5dp"
            android:orientation="vertical">

            <ImageView
                android:id="@+id/switchFacingButton"
                android:layout_width="33dp"
                android:layout_height="33dp"
                android:layout_gravity="center_horizontal"
                android:src="@mipmap/camera_id" />

            <!--<TextView-->
            <!--android:layout_width="wrap_content"-->
            <!--android:layout_height="wrap_content"-->
            <!--android:layout_gravity="center_horizontal"-->
            <!--android:layout_marginTop="4dp"-->
            <!--android:text="切换"-->
            <!--android:textColor="#fff" />-->

        </LinearLayout>

        <LinearLayout
            android:id="@+id/zoomLayout"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="6dp"
            android:orientation="vertical"
            android:visibility="gone">

            <ImageView
                android:id="@+id/zoomButton"
                android:layout_width="33dp"
                android:layout_height="33dp"
                android:layout_gravity="center_horizontal"
                android:background="@mipmap/icon_focus"
                android:contentDescription="@null" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:layout_marginTop="4dp"
                android:text="变焦"
                android:textColor="@color/white" />

        </LinearLayout>

        <LinearLayout
            android:id="@+id/openRecordLayout"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="6dp"
            android:orientation="vertical"
            android:visibility="gone">

            <ImageView
                android:id="@+id/openRecordButton"
                android:layout_width="33dp"
                android:layout_height="33dp"
                android:layout_gravity="center_horizontal"
                android:src="@mipmap/record" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:layout_marginTop="4dp"
                android:text="录制"
                android:textColor="#fff" />

        </LinearLayout>


    </LinearLayout>


</RelativeLayout>

6.推流的地址要在官网申请
7.需要注意的是:蓝牙是否打开会影响推流,使得项目出现闪退;解决方法在manifest文件加上


##结束

本文地址:https://blog.csdn.net/dream2222222/article/details/107529791

相关标签: android