123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551 |
- package com.example.plugina;
- import android.content.Context;
- import android.content.res.Configuration;
- import android.graphics.Bitmap;
- import android.graphics.BitmapFactory;
- import android.graphics.PixelFormat;
- import android.hardware.Camera;
- import android.os.Build;
- import android.os.Environment;
- import android.os.Handler;
- import android.os.Looper;
- import android.util.Log;
- import android.view.Gravity;
- import android.view.MotionEvent;
- import android.view.SurfaceHolder;
- import android.view.View;
- import android.view.WindowManager;
- import android.widget.ImageView;
- import android.widget.TextView;
- import android.widget.Toast;
- import com.bingo.apkloader.base.ApkContext;
- import com.bingo.apkloader.base.ApkWindowBuild;
- import com.github.faucamp.simplertmp.RtmpHandler;
- import net.ossrs.yasea.SrsCameraView;
- import net.ossrs.yasea.SrsEncodeHandler;
- import net.ossrs.yasea.SrsPublisher;
- import net.ossrs.yasea.SrsRecordHandler;
- import java.io.File;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.net.SocketException;
- public class ViewPush implements
- RtmpHandler.RtmpListener, SrsRecordHandler.SrsRecordListener, SrsEncodeHandler.SrsEncodeListener,
- SurfaceHolder.Callback, View.OnTouchListener, View.OnClickListener {
- private static final String TAG = "ViewPush";
- private ApkWindowBuild apkWindowBuild;
- private ApkContext apkContext;
- private WindowManager windowManager;
- private WindowManager.LayoutParams windowParams;
- private String pushUrl;
- private String apiBaseUrl;
- private String userId;
- private String token;
- private String sourceType;
- private String group;
- private String owner;
- private String orientation;
- private boolean destroyed = false;
- private int mWidth = 640;
- private int mHeight = 480;
- private static final long DOUBLE_BACK_TOUCH_INTERVAL = 2000; // 两次按下返回键的时间间隔,单位为毫秒
- private long mLastBackPressTime = 0;
- private SrsPublisher mPublisher;
- private SrsCameraView mCameraView;
- private TextView txtOnlineCount;
- private View contentView = null;
- private Handler mainLooperHandler = new Handler(Looper.getMainLooper());
- public ViewPush(ApkContext apkContext, ApkWindowBuild apkWindowBuild,String pushUrl,
- String apiBaseUrl,
- String userId,
- String token,
- String sourceType,
- String group,
- String owner,
- String orientation) {
- this.pushUrl = pushUrl;
- this.apiBaseUrl = apiBaseUrl;
- this.userId = userId;
- this.token = token;
- this.sourceType = sourceType;
- this.group = group;
- this.owner = owner;
- this.orientation = orientation;
- this.apkContext = apkContext;
- this.apkWindowBuild = apkWindowBuild;
- this.contentView = this.apkWindowBuild.Inflate(R.layout.view_push);
- this.init();
- }
- public void show(){
- mCameraView = this.contentView.findViewById(R.id.glsurfaceview_camera);
- mCameraView.setInitPreviewOrientation("horizontal".equals(this.orientation) ? Configuration.ORIENTATION_LANDSCAPE : Configuration.ORIENTATION_PORTRAIT);
- mCameraView.setOnTouchListener(this);
- mCameraView.setCameraCallbacksHandler(new SrsCameraView.CameraCallbacksHandler(){
- @Override
- public void onCameraParameters(Camera.Parameters params) {
- }
- });
- mPublisher = new SrsPublisher(mCameraView);
- mPublisher.setEncodeHandler(new SrsEncodeHandler(this));
- mPublisher.setRtmpHandler(new RtmpHandler(this));
- mPublisher.setRecordHandler(new SrsRecordHandler(this));
- mPublisher.setPreviewResolution(mWidth, mHeight);
- mPublisher.setOutputResolution(mHeight, mWidth); // 这里要和preview反过来
- mPublisher.setVideoHDMode();
- this.contentView.findViewById(R.id.ivClose).setOnClickListener(this);
- this.contentView.findViewById(R.id.btnSwitch).setOnClickListener(this);
- this.contentView.findViewById(R.id.btnEnableAudio).setOnClickListener(this);
- this.contentView.findViewById(R.id.btnCapture).setOnClickListener(this);
- this.contentView.findViewById(R.id.ivFullscreen).setOnClickListener(this);
- handler.post(httpRequestRunnable);
- mainLooperHandler.post(new Runnable() {
- @Override
- public void run() {
- // startPush();
- }
- });
- if (windowManager == null) {
- windowManager = (WindowManager) this.apkContext.getContext().getSystemService(Context.WINDOW_SERVICE);
- }
- if (windowParams == null) {
- int LAYOUT_FLAG;
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
- } else {
- LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_PHONE;
- }
- // 初始化LayoutParams
- windowParams = new WindowManager.LayoutParams(
- WindowManager.LayoutParams.MATCH_PARENT,
- WindowManager.LayoutParams.MATCH_PARENT,
- WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
- WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
- PixelFormat.TRANSLUCENT
- );
- }
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
- windowParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
- }else{
- windowParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
- }
- windowParams.gravity = Gravity.START | Gravity.TOP;
- if ("horizontal".equals(this.orientation)){
- int maxScreenWidth = windowManager.getDefaultDisplay().getWidth();
- windowParams.width = (int)(maxScreenWidth * 0.5);
- windowParams.x = windowParams.width;
- }else{
- int maxScreenHeight = windowManager.getDefaultDisplay().getHeight();
- windowParams.height = (int)(maxScreenHeight * 0.5);
- windowParams.y = windowParams.height;
- }
- Log.d(TAG, "-->show this.apkWindowBuild.AddView");
- this.apkWindowBuild.AddView(this.contentView, windowParams);
- }
- private void init() {
- txtOnlineCount = this.contentView.findViewById(R.id.txtOnlineCount);
- }
- private void startPush() {
- mPublisher.startCamera();
- mPublisher.startPublish(this.pushUrl);
- }
- ////////////////////////////////////////////get和set///////////////////////////////////////////////
- public static String getTAG() {
- return TAG;
- }
- public ApkWindowBuild getApkWindowBuild() {
- return apkWindowBuild;
- }
- public void setApkViewBuild(ApkWindowBuild apkWindowBuild) {
- this.apkWindowBuild = apkWindowBuild;
- }
- public String getPushUrl() {
- return pushUrl;
- }
- public void setPushUrl(String pushUrl) {
- this.pushUrl = pushUrl;
- }
- public String getApiBaseUrl() {
- return apiBaseUrl;
- }
- public void setApiBaseUrl(String apiBaseUrl) {
- this.apiBaseUrl = apiBaseUrl;
- }
- public String getUserId() {
- return userId;
- }
- public void setUserId(String userId) {
- this.userId = userId;
- }
- public String getToken() {
- return token;
- }
- public void setToken(String token) {
- this.token = token;
- }
- public String getSourceType() {
- return sourceType;
- }
- public void setSourceType(String sourceType) {
- this.sourceType = sourceType;
- }
- public String getGroup() {
- return group;
- }
- public void setGroup(String group) {
- this.group = group;
- }
- public String getOwner() {
- return owner;
- }
- public void setOwner(String owner) {
- this.owner = owner;
- }
- private void close(){
- this.destroyed = true;
- mPublisher.stopPublish();
- mPublisher.stopRecord();
- // if (Main.liveBroadcastId != null && !Main.liveBroadcastId.isEmpty()){
- // new Thread(new Runnable() {
- // @Override
- // public void run() {
- // HttpUtil.shutdownLiveBroadcast(ViewPush.this.apiBaseUrl, ViewPush.this.token, Main.liveBroadcastId);
- // }
- // }).start();
- // }
- this.apkWindowBuild.removeView(this.contentView);
- }
- @Override
- public void surfaceCreated(SurfaceHolder holder) {
- }
- @Override
- public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
- }
- @Override
- public void surfaceDestroyed(SurfaceHolder holder) {
- }
- @Override
- public void onClick(View v) {
- if (v.getId() == R.id.ivClose){
- long currentTime = System.currentTimeMillis();
- if (currentTime - mLastBackPressTime > DOUBLE_BACK_TOUCH_INTERVAL) {
- mLastBackPressTime = currentTime;
- Toast.makeText(this.contentView.getContext(), "再按一次退出直播", Toast.LENGTH_SHORT).show();
- } else {
- this.close();
- }
- }else if (v.getId() == R.id.btnSwitch){
- mPublisher.switchCameraFace((mPublisher.getCameraId() + 1) % Camera.getNumberOfCameras());
- }else if(v.getId() == R.id.btnEnableAudio){
- if (v.getTag() == null){
- mPublisher.setSendVideoOnly(true);
- ((ImageView)v).setImageResource(R.drawable.microphone_off);
- v.setTag(1);
- }else{
- mPublisher.setSendVideoOnly(false);
- ((ImageView)v).setImageResource(R.drawable.microphone_on);
- v.setTag(null);
- }
- }else if(v.getId() == R.id.btnCapture){
- takePicture();
- }else if(v.getId() == R.id.ivFullscreen){
- Object tag = v.getTag();
- if (tag == null || tag.toString() == "full_screen"){
- this.updateContentViewFullscreen(true);
- ((ImageView)v).setImageResource(R.drawable.normal_screen);
- v.setTag("normal_screen");
- }else{
- this.updateContentViewFullscreen(false);
- ((ImageView)v).setImageResource(R.drawable.full_screen);
- v.setTag("full_screen");
- }
- }
- }
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- int action = event.getAction();
- if (event.getPointerCount() > 1) {
- if (action == MotionEvent.ACTION_MOVE) {
- mCameraView.setZoom(event);
- }
- }
- return true;
- }
- /**
- * 设置是否为全屏
- * @param full
- */
- private void updateContentViewFullscreen(boolean full){
- if (full){
- if ("horizontal".equals(this.orientation)){
- this.windowParams.width = WindowManager.LayoutParams.MATCH_PARENT;
- }else{
- this.windowParams.height = WindowManager.LayoutParams.MATCH_PARENT;
- }
- }else{
- if ("horizontal".equals(this.orientation)){
- int maxScreenWidth = windowManager.getDefaultDisplay().getWidth();
- this.windowParams.width = (int)(maxScreenWidth * 0.5);
- this.windowParams.x = windowParams.width;
- }else{
- int maxScreenHeight = windowManager.getDefaultDisplay().getHeight();
- this.windowParams.height = (int)(maxScreenHeight * 0.5);
- this.windowParams.y = windowParams.height;
- }
- }
- //// this.apkWindowBuild.updateViewLayout(this.contentView, this.windowParams);
- }
- // 截图方法
- private void takePicture() {
- if(this.mCameraView.getCamera() != null) {
- this.mCameraView.getCamera().takePicture(null, null, new Camera.PictureCallback() {
- @Override
- public void onPictureTaken(byte[] data, Camera camera) {
- // data就是图片的字节数组
- Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
- // 保存图片
- saveBitmap(bitmap);
- // 重新开始预览
- camera.startPreview();
- }
- });
- }
- }
- private void saveBitmap(Bitmap bitmap) {
- String fileName = "IMG_" + System.currentTimeMillis() + ".jpg";
- File file = new File(this.contentView.getContext().getExternalFilesDir(Environment.DIRECTORY_PICTURES), fileName);
- try (FileOutputStream fos = new FileOutputStream(file)) {
- bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
- fos.flush();
- } catch (IOException e) {
- Log.e(TAG, e.getMessage());
- e.printStackTrace();
- }
- }
- private Handler handler = new Handler();
- private Runnable httpRequestRunnable = new Runnable() {
- @Override
- public void run() {
- if (ViewPush.this.destroyed){
- Log.d(TAG, "exit request task");
- return;
- }
- updateTextViewContent();
- // 每隔3秒发起一次HTTP请求
- handler.postDelayed(this, 3000);
- }
- };
- private void updateTextViewContent() {
- new Thread(new Runnable() {
- @Override
- public void run() {
- try {
- // if (Main.liveBroadcastId.isEmpty()){
- // return;
- // }
- final long count = 0; //HttpUtil.fetchOnlineCount(ViewPush.this.apiBaseUrl, ViewPush.this.token, Main.liveBroadcastId, "push", "");
- // 在UI线程更新TextView内容
- ViewPush.this.contentView.post(new Runnable() {
- @Override
- public void run() {
- ViewPush.this.txtOnlineCount.setText("在线观看人数:" + count);
- }
- });
- } catch (Exception e) {
- Log.e(TAG, e.getMessage());
- }
- }
- }).start();
- }
- private String getCreateJsonString() {
- String formatStr = "{\"sourceType\":\"%s\", \"objectId\":\"%s\", \"config\":\"{}\", \"owner\":\"%s\", \"group\":\"%s\", \"status\":%d}";
- return String.format(formatStr, this.sourceType, this.userId, this.owner, this.group.trim().isEmpty() ? "72-0" : this.group.trim(), 10);
- }
- @Override
- public void onRtmpConnecting(String s) {
- Toast.makeText(ViewPush.this.contentView.getContext(), "连接中", Toast.LENGTH_SHORT).show();
- }
- @Override
- public void onRtmpConnected(String s) {
- mainLooperHandler.post(new Runnable() {
- @Override
- public void run() {
- // // 空的则代表需要创建直播
- // new Thread(new Runnable() {
- // @Override
- // public void run() {
- // if (ViewPush.this.destroyed){
- // return;
- // }
- // if (Main.liveBroadcastId.isEmpty()) {
- // Main.liveBroadcastId = HttpUtil.createLiveBroadcase(ViewPush.this.apiBaseUrl, ViewPush.this.token, ViewPush.this.getCreateJsonString());
- // }else{
- // HttpUtil.openLiveBroadcast(ViewPush.this.apiBaseUrl, ViewPush.this.token, Main.liveBroadcastId);
- // }
- // }
- // }).start();
- Toast.makeText(ViewPush.this.contentView.getContext(), "连接成功", Toast.LENGTH_SHORT).show();
- }
- });
- }
- @Override
- public void onRtmpVideoStreaming() {
- }
- @Override
- public void onRtmpAudioStreaming() {
- }
- @Override
- public void onRtmpStopped() {
- }
- @Override
- public void onRtmpDisconnected() {
- }
- @Override
- public void onRtmpVideoFpsChanged(double v) {
- }
- @Override
- public void onRtmpVideoBitrateChanged(double v) {
- }
- @Override
- public void onRtmpAudioBitrateChanged(double v) {
- }
- @Override
- public void onRtmpSocketException(SocketException e) {
- }
- @Override
- public void onRtmpIOException(IOException e) {
- }
- @Override
- public void onRtmpIllegalArgumentException(IllegalArgumentException e) {
- }
- @Override
- public void onRtmpIllegalStateException(IllegalStateException e) {
- }
- @Override
- public void onNetworkWeak() {
- }
- @Override
- public void onNetworkResume() {
- }
- @Override
- public void onEncodeIllegalArgumentException(IllegalArgumentException e) {
- }
- @Override
- public void onRecordPause() {
- }
- @Override
- public void onRecordResume() {
- }
- @Override
- public void onRecordStarted(String s) {
- }
- @Override
- public void onRecordFinished(String s) {
- }
- @Override
- public void onRecordIllegalArgumentException(IllegalArgumentException e) {
- }
- @Override
- public void onRecordIOException(IOException e) {
- }
- }
|