/* * MainActivity.java * MainActivity * * Github: https://github.com/daniulive/SmarterStreaming * * Created by DaniuLive on 2016/12/12. * Copyright © 2014~2016 DaniuLive. All rights reserved. */ package com.daniulive.smartpublisher; import android.annotation.SuppressLint; import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.Intent; import android.media.projection.MediaProjectionManager; import android.os.Build; import android.os.Bundle; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.EditText; import android.widget.Spinner; import android.widget.TextView; import android.widget.Toast; import android.widget.AdapterView.OnItemSelectedListener; public class MainActivity extends Activity { MediaProjectionManager mMediaProjectionManager; private static final int REQUEST_MEDIA_PROJECTION = 1; private static final String TAG = "DaniuliveActivity"; static int mResultCode; static Intent mResultData; private Spinner typeSelector; private Spinner cameraResolutionSelector; private Spinner screenResolutionSelector; private Spinner recorderSelector; private Button btnRecoderMgr; private Button btnHWencoder; private Button btnSwitchCamera; private Button btnInputPushUrl; private Button btnPermissionCheck; private Button btnCapture; private boolean is_need_local_recorder = false; // do not enable recorder in // default private boolean isCameraFaceFront = false; // 当前打开的摄像头标记 private boolean is_hardware_encoder = false; private boolean isStart = false; final private String baseURL = "rtmp://player.daniulive.com:1935/hls/stream"; private String inputPushURL = ""; private TextView textCurURL = null; private String printText = "URL:"; private int videoWidth = 640; private int videoHight = 480; private String publishURL = "rtmp://player.daniulive.com:1935/hls/streamservice"; private final int PUSH_TYPE_SCREEN = 0; private final int PUSH_TYPE_CAMERA = 1; private int pushType = PUSH_TYPE_SCREEN; private final int SCREEN_RESOLUTION_STANDARD = 0; private final int SCREEN_RESOLUTION_LOW = 1; private int screenResolution = SCREEN_RESOLUTION_STANDARD; private String recDir = "/sdcard/daniulive/rec"; // for recorder path BackgroudService bgService; private Intent intent = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); intent = new Intent(MainActivity.this, BackgroudService.class); typeSelector = (Spinner) findViewById(R.id.pushTpyeSelctor); final String[] pushTypeSel = new String[] { "推送屏幕", "推送摄像头" }; ArrayAdapter<String> adapterPushType = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, pushTypeSel); adapterPushType .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); typeSelector.setAdapter(adapterPushType); typeSelector.setOnItemSelectedListener(new OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { if (isStart) { Log.e(TAG, "Could not switch push type during publishing.."); return; } Log.i(TAG, "[推送类型]Currently choosing: " + pushTypeSel[position]); SwitchPushType(position); } @Override public void onNothingSelected(AdapterView<?> parent) { } }); cameraResolutionSelector = (Spinner) findViewById(R.id.camera_resolution_selctor); final String[] resolutionSel = new String[] { "摄像头高分辨率", "摄像头中分辨率", "摄像头低分辨率", "摄像头超高分辨率" }; ArrayAdapter<String> adapterResolution = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, resolutionSel); adapterResolution .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); cameraResolutionSelector.setAdapter(adapterResolution); cameraResolutionSelector .setOnItemSelectedListener(new OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { if (isStart) { Log.e(TAG, "Could not switch resolution during publishing.."); return; } Log.i(TAG, "[推送分辨率]Currently choosing: " + resolutionSel[position]); SwitchResolution(position); } @Override public void onNothingSelected(AdapterView<?> parent) { } }); screenResolutionSelector = (Spinner) findViewById(R.id.screen_resolution_selctor); final String[] sceenResolutionSel = new String[] { "屏幕标准分辨率", "屏幕低分辨率" }; ArrayAdapter<String> adapterScreenResolution = new ArrayAdapter<String>( this, android.R.layout.simple_spinner_item, sceenResolutionSel); adapterScreenResolution .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); screenResolutionSelector.setAdapter(adapterScreenResolution); screenResolutionSelector .setOnItemSelectedListener(new OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { if (isStart) { Log.e(TAG, "Could not switch screen resolution during publishing.."); return; } Log.i(TAG, "[推送屏幕分辨率]Currently choosing: " + sceenResolutionSel[position]); SwitchScreenResolution(position); } @Override public void onNothingSelected(AdapterView<?> parent) { } }); // Recorder related settings recorderSelector = (Spinner) findViewById(R.id.recoder_selctor); final String[] recoderSel = new String[] { "本地不录像", "本地录像" }; ArrayAdapter<String> adapterRecoder = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, recoderSel); adapterRecoder .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); recorderSelector.setAdapter(adapterRecoder); recorderSelector .setOnItemSelectedListener(new OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { Log.i(TAG, "Currently choosing: " + recoderSel[position]); if (1 == position) { is_need_local_recorder = true; } else { is_need_local_recorder = false; } } @Override public void onNothingSelected(AdapterView<?> parent) { } }); btnRecoderMgr = (Button) findViewById(R.id.button_recoder_manage); btnRecoderMgr.setOnClickListener(new ButtonRecorderMangerListener()); btnSwitchCamera = (Button) findViewById(R.id.button_switch_camera); btnSwitchCamera.setOnClickListener(new ButtonSwitchCameraListener()); btnHWencoder = (Button) findViewById(R.id.button_hwencoder); btnHWencoder.setOnClickListener(new ButtonHardwareEncoderListener()); btnInputPushUrl = (Button) findViewById(R.id.button_input_push_url); btnInputPushUrl.setOnClickListener(new ButtonInputPushUrlListener()); btnPermissionCheck = (Button) findViewById(R.id.permission_check); btnPermissionCheck.setOnClickListener(new OnClickListener() { @SuppressLint("NewApi") @Override public void onClick(View v) { if (pushType == PUSH_TYPE_SCREEN) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { mMediaProjectionManager = (MediaProjectionManager) getApplicationContext() .getSystemService(MEDIA_PROJECTION_SERVICE); startActivityForResult(mMediaProjectionManager .createScreenCaptureIntent(), REQUEST_MEDIA_PROJECTION); } } } }); btnCapture = (Button) findViewById(R.id.button_start_stop_capture); btnCapture.setEnabled(false); btnCapture.setOnClickListener(new OnClickListener() { @SuppressLint("NewApi") @Override public void onClick(View v) { if (!isStart) { Log.i(TAG, "Start publisher.."); intent.putExtra("PUSHTYPE", pushType); intent.putExtra("CAMERAWIDTH", videoWidth); intent.putExtra("CAMERAHEIGHT", videoHight); intent.putExtra("SCREENRESOLUTION", screenResolution); if (inputPushURL != null && inputPushURL.length() > 1) { publishURL = inputPushURL; Log.i(TAG, "start, input publish url:" + publishURL); } else { publishURL = baseURL + String.valueOf((int) (System .currentTimeMillis() % 1000000)); Log.i(TAG, "start, generate random url:" + publishURL); } printText = "URL:" + publishURL; Log.i(TAG, printText); textCurURL = (TextView) findViewById(R.id.txtCurURL); textCurURL.setText(printText); intent.putExtra("PUBLISHURL", publishURL); intent.putExtra("RECORDER", is_need_local_recorder); intent.putExtra("HWENCODER", is_hardware_encoder); intent.putExtra("SWITCHCAMERA", isCameraFaceFront); startService(intent); isStart = true; btnCapture.setText("停止推送"); cameraResolutionSelector.setEnabled(false); screenResolutionSelector.setEnabled(false); recorderSelector.setEnabled(false); btnRecoderMgr.setEnabled(false); btnInputPushUrl.setEnabled(false); btnHWencoder.setEnabled(false); btnSwitchCamera.setEnabled(false); } else { Log.i(TAG, "Stop publisher.."); stopService(intent); isStart = false; btnCapture.setText("开始推流"); if (pushType == PUSH_TYPE_SCREEN) { btnCapture.setEnabled(false); cameraResolutionSelector.setEnabled(false); screenResolutionSelector.setEnabled(true); btnPermissionCheck.setEnabled(true); btnSwitchCamera.setEnabled(false); } else { btnCapture.setEnabled(true); cameraResolutionSelector.setEnabled(true); screenResolutionSelector.setEnabled(false); btnPermissionCheck.setEnabled(false); btnSwitchCamera.setEnabled(true); } recorderSelector.setEnabled(true); btnRecoderMgr.setEnabled(true); btnInputPushUrl.setEnabled(true); btnHWencoder.setEnabled(true); btnSwitchCamera.setEnabled(true); } } }); } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == REQUEST_MEDIA_PROJECTION) { if (resultCode != Activity.RESULT_OK) { Log.e(TAG, "User cancelled"); Toast.makeText(this, "User cancelled", Toast.LENGTH_SHORT) .show(); return; } mResultCode = resultCode; mResultData = data; btnPermissionCheck.setEnabled(false); btnCapture.setEnabled(true); } } void SwitchPushType(int position) { Log.i(TAG, "Current push type position: " + position); switch (position) { case 0: pushType = PUSH_TYPE_SCREEN; cameraResolutionSelector.setEnabled(false); screenResolutionSelector.setEnabled(true); btnPermissionCheck.setEnabled(true); btnSwitchCamera.setEnabled(false); btnCapture.setEnabled(false); break; case 1: pushType = PUSH_TYPE_CAMERA; cameraResolutionSelector.setEnabled(true); screenResolutionSelector.setEnabled(false); btnPermissionCheck.setEnabled(false); btnCapture.setEnabled(true); btnSwitchCamera.setEnabled(true); btnCapture.setEnabled(true); break; default: pushType = PUSH_TYPE_SCREEN; } } void SwitchResolution(int position) { Log.i(TAG, "Current Resolution position: " + position); switch (position) { case 0: videoWidth = 640; videoHight = 480; break; case 1: videoWidth = 320; videoHight = 240; break; case 2: videoWidth = 176; videoHight = 144; break; case 3: videoWidth = 1280; videoHight = 720; break; default: videoWidth = 640; videoHight = 480; } } void SwitchScreenResolution(int position) { Log.i(TAG, "Current Screen Resolution position: " + position); switch (position) { case 0: screenResolution = SCREEN_RESOLUTION_STANDARD; break; case 1: screenResolution = SCREEN_RESOLUTION_LOW; break; default: screenResolution = SCREEN_RESOLUTION_STANDARD; } } class ButtonSwitchCameraListener implements OnClickListener { public void onClick(View v) { isCameraFaceFront = !isCameraFaceFront; if (isCameraFaceFront) btnSwitchCamera.setText("当前前置摄像头"); else btnSwitchCamera.setText("当前后置摄像头"); } } class ButtonHardwareEncoderListener implements OnClickListener { public void onClick(View v) { is_hardware_encoder = !is_hardware_encoder; if (is_hardware_encoder) btnHWencoder.setText("当前硬编码"); else btnHWencoder.setText("当前软编码"); } } private void PopInputUrlDialog() { final EditText inputUrlTxt = new EditText(this); inputUrlTxt.setFocusable(true); inputUrlTxt.setText(baseURL + String.valueOf((int) (System.currentTimeMillis() % 1000000))); AlertDialog.Builder builderUrl = new AlertDialog.Builder(this); builderUrl.setTitle("如 rtmp://player.daniulive.com:1935/hls/stream123456") .setView(inputUrlTxt).setNegativeButton("取消", null); builderUrl.setPositiveButton("确认", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { String fullPushUrl = inputUrlTxt.getText().toString(); SaveInputUrl(fullPushUrl); } }); builderUrl.show(); } private void SaveInputUrl(String url) { inputPushURL = ""; if (url == null) return; // rtmp:// if (url.length() < 8) { Log.e(TAG, "Input publish url error:" + url); return; } if (!url.startsWith("rtmp://")) { Log.e(TAG, "Input publish url error:" + url); return; } inputPushURL = url; } class ButtonInputPushUrlListener implements OnClickListener { public void onClick(View v) { PopInputUrlDialog(); } } class ButtonRecorderMangerListener implements OnClickListener { public void onClick(View v) { Intent intent = new Intent(); intent.setClass(MainActivity.this, RecorderManager.class); intent.putExtra("RecoderDir", recDir); startActivity(intent); } } }