這篇文章介紹了如何用Wowza Gocoder SDK Android版開發(fā)一個基本功能的直播APP。

一、創(chuàng)建一個新的開發(fā)項(xiàng)目
首先你需要在Android Studio中創(chuàng)建一個APP開發(fā)項(xiàng)目。
二、添加一個直播按鈕
在這一步,你需要在APP的界面上添加一個直播按鈕.
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:wowza="http://schemas.android.com/apk/res-auto"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.mycompany.myapp.MainActivity">
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/camera_preview"
wowza:scaleMode="fill"
wowza:defaultCamera="back"
wowza:frameSizePreset="frameSize1280x720"/>
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Broadcast"
android:id="@+id/broadcast_button"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true" />
在 [project_root]/app/src/main/AndroidManifest.xml 文件中,為 activity 元素添加 android:configChanges 參數(shù)。
android:configChanges="orientation|keyboardHidden|screenSize">
為 MainActivity Class添加 onWindowFocusChanged() 方法,以此來開啟Android的immersive full-screen 模式。
?
//
?
// Enable Android's sticky immersive full-screen mode
?
//
?
@Override
?
public void onWindowFocusChanged(boolean hasFocus) {
?
super.onWindowFocusChanged(hasFocus);
?
?
View rootView = getWindow().getDecorView().findViewById(android.R.id.content);
?
if (rootView != null)
?
rootView.setSystemUiVisibility(
?
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
?
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
?
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
?
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
?
| View.SYSTEM_UI_FLAG_FULLSCREEN
?
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
?
}
三、定義APP的參數(shù)
在 MainActivity.java 文件中為 MainActivity Class 添加下面的成員變量:
public class MainActivity extendsAppCompatActivity {
// The top level GoCoder API interface
private WowzaGoCoder goCoder;
// The GoCoder SDK camera view
private WZCameraView goCoderCameraView;
// The GoCoder SDK audio device
private WZAudioDevice goCoderAudioDevice;
// The broadcast configuration settings
private WZBroadcastConfig goCoderBroadcastConfig;
// Properties needed for Android 6+ permissions handling
private static final intPERMISSIONS_REQUEST_CODE = 0x1;
private boolean mPermissionsGranted = true;
private String[] mRequiredPermissions = new String[] {
Manifest.permission.CAMERA,
Manifest.permission.RECORD_AUDIO
};
四、注冊和初始化SDK
在這一步,你需要在 MainActivity Class的 onCreate() 方法中添加下面的代碼來注冊和初始化GoCoder SDK 的License。
請用你的License key替換下面的 GOSK-XXXX-XXXX-XXXX-XXXX-XXXX 。
// Initialize the GoCoder SDK
goCoder =WowzaGoCoder.init(getApplicationContext(), "GOSK-XXXX-XXXX-XXXX-XXXX-XXXX");
if (goCoder == null) {
// If initialization failed, retrieve the last error and display it
WZError goCoderInitError = WowzaGoCoder.getLastError();
Toast.makeText(this,
"GoCoder SDK error: " +goCoderInitError.getErrorDescription(),
Toast.LENGTH_LONG).show();
return;
}
五、檢查APP的權(quán)限
接下來,你必須為APP定義它所需要的權(quán)限:
?
xmlns:android="http://schemas.android.com/apk/res/android"
?
package="com.cintimedia.foobar">
對于Android 6.0及以上版本,你需要在 MainActivity class中添加 onResume() 和 onRequestPermissionsResult() 方法來檢查用戶已經(jīng)授權(quán)APP來訪問攝像頭和麥克風(fēng)。
?
//
// Called when an activity is brought to the foreground
//
@Override
protected void onResume() {
super.onResume();
// If running on Android 6 (Marshmallow) or above, check to see if the necessary permissions
?
// have been granted
?
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
?
mPermissionsGranted = hasPermissions(this, mRequiredPermissions);
?
if (!mPermissionsGranted)
?
ActivityCompat.requestPermissions(this, mRequiredPermissions, PERMISSIONS_REQUEST_CODE);
?
} else
mPermissionsGranted = true;
}
//
?
// Callback invoked in response to a call to ActivityCompat.requestPermissions() to interpret
?
// the results of the permissions request
?
//
?
@Override
?
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
mPermissionsGranted = true;
?
switch (requestCode) {
?
case PERMISSIONS_REQUEST_CODE: {
?
// Check the result of each permission granted
?
for(int grantResult : grantResults) {
?
if (grantResult != PackageManager.PERMISSION_GRANTED) {
?
mPermissionsGranted = false;
?
}
?
}
?
}
?
}
?
}
?
//
?
// Utility method to check the status of a permissions request for an array of permission identifiers
//
?
private static boolean hasPermissions(Context context, String[] permissions) {
?
for(String permission : permissions)
?
if (context.checkCallingOrSelfPermission(permission) != PackageManager.PERMISSION_GRANTED)
?
return false;
?
return true;
?
}
六、開啟攝像頭預(yù)覽
接下來,我們需要配置和開啟攝像頭預(yù)覽:
?
// Associate the WZCameraView defined in the U/I layout with the corresponding class member
goCoderCameraView = (WZCameraView) findViewById(R.id.camera_preview);
?
// Create an audio device instance for capturing and broadcasting audio
?
goCoderAudioDevice = new WZAudioDevice();
?
// Start the camera preview display
if (mPermissionsGranted && goCoderCameraView != null) {
if (goCoderCameraView.isPreviewPaused())
goCoderCameraView.onResume();
else
goCoderCameraView.startPreview();
}
?
七、配置直播相關(guān)參數(shù)
在 MainActivity Class的 onCreate 方法中加入對直播的相關(guān)參數(shù),包括服務(wù)器地址(hostAddress)、端口(portNumber)、 應(yīng)用名(applicationName)和流名(streamName)。這個服務(wù)器不限于Wowza Streaming Engine或Wowza Streaming Cloud。
如果你要往Wowza Streaming Cloud 云平臺推流,那么你可以在Wowza Streaming Cloud的Web界面的live streaming詳情的 Overview Tab頁上找到 Connection Code
// Get a copy of the active config
WowzaConfig *goCoderBroadcastConfig =self.goCoder.config;
// Set the defaults for 720p video
[goCoderBroadcastConfigloadPreset:WZFrameSizePreset1280x720];
// Set the connection properties for thetarget Wowza Streaming Engine server or Wowza Cloud account
goCoderBroadcastConfig.hostAddress =@"live.someserver.net";
goCoderBroadcastConfig.portNumber =1935;
goCoderBroadcastConfig.applicationName =@"live";
goCoderBroadcastConfig.streamName =@"myStream";
// Update the active config
self.goCoder.config =goCoderBroadcastConfig;
八、添加流傳輸?shù)臓顟B(tài)回調(diào)
在這一步,我們添加對流傳輸狀態(tài)監(jiān)控的回調(diào)。
1、我們首先要在primary activity( MainActivity )添加WZStatusCallback接口,用來對直播流的傳輸做狀態(tài)監(jiān)控:
// Main app activity class
public class MainActivity extends AppCompatActivity
implements WZStatusCallback {
2、在 MainActivity Class中添加WZStatusCallback接口中定義的方法:
//
// The callback invoked upon changes tothe state of the steaming broadcast
//
@Override
public void onWZStatus(final WZStatusgoCoderStatus) {
// A successful status transition has beenreported by the GoCoder SDK
final StringBuffer statusMessage = newStringBuffer("Broadcast status: ");
switch (goCoderStatus.getState()) {
case WZState.STARTING:
statusMessage.append("Broadcast initialization");
break;
case WZState.READY:
statusMessage.append("Ready to begin streaming");
break;
case WZState.RUNNING:
statusMessage.append("Streaming is active");
break;
case WZState.STOPPING:
statusMessage.append("Broadcast shutting down");
break;
case WZState.IDLE:
statusMessage.append("The broadcast is stopped");
break;
default:
return;
}
// Display the status message using the U/Ithread
new Handler(Looper.getMainLooper()).post(newRunnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, statusMessage,Toast.LENGTH_LONG).show();
}
});
}
//
// The callback invoked when an erroroccurs during a broadcast
//
@Override
public void onWZError(final WZStatusgoCoderStatus) {
// If an error is reported by the GoCoder SDK,display a message
// containing the error details using the U/Ithread
new Handler(Looper.getMainLooper()).post(newRunnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this,
"Streaming error: " +goCoderStatus.getLastError().getErrorDescription(),
Toast.LENGTH_LONG).show();
}
});
}
九、開始直播
在開始直播之前,您還需要為直播按鈕加上啟動和停止直播的代碼:
在 MainActivity Class中添加 View.onClickListener 接口:
// Main app activity class
public class MainActivity extends AppCompatActivity
implements WZStatusCallback, View.OnClickListener {
在 MainActivity Class的 onCreate() 方法的最底部,它在直播按鈕被按下時被調(diào)用:
//
// The callback invoked when the broadcast button is pressed
?
//
?
@Override
?
public void onClick(View view) {
?
// return if the user hasn't granted the app the necessary permissions
?
if (!mPermissionsGranted) return;
?
// Ensure the minimum set of configuration settings have been specified necessary to
?
// initiate a broadcast streaming session
WZStreamingError configValidationError = goCoderBroadcastConfig.validateForBroadcast();
if (configValidationError != null) {
Toast.makeText(this, configValidationError.getErrorDescription(), Toast.LENGTH_LONG).show();
} else if (goCoderBroadcaster.getStatus().isRunning()) {
?
// Stop the broadcast that is currently running
goCoderBroadcaster.endBroadcast(this);
} else {
// Start streaming
goCoderBroadcaster.startBroadcast(goCoderBroadcastConfig, this);
}
}
?
?
// Associate the onClick() method as the callback for the broadcast button's click event
Button broadcastButton = (Button) findViewById(R.id.broadcast_button);
broadcastButton.setOnClickListener(this);
十、構(gòu)建和運(yùn)行你的APP
最后,可以編譯和測試的APP了,請點(diǎn)擊 Run 菜單,選擇 Run 或者 Debug 。
十一、MainActivity的例子程序
下面是一個完整的 MainActivity Class的例子,代碼包括上面講到的所有內(nèi)容:
public class MainActivity extendsAppCompatActivity
implements WZStatusCallback, View.OnClickListener {
// The top level GoCoder API interface
private WowzaGoCoder goCoder;
// The GoCoder SDK camera view
private WZCameraView goCoderCameraView;
// The GoCoder SDK audio device
private WZAudioDevice goCoderAudioDevice;
// The GoCoder SDK broadcaster
private WZBroadcast goCoderBroadcaster;
// The broadcast configuration settings
private WZBroadcastConfig goCoderBroadcastConfig;
// Properties needed for Android 6+ permissions handling
private static final int PERMISSIONS_REQUEST_CODE = 0x1;
private boolean mPermissionsGranted = true;
private String[] mRequiredPermissions = new String[] {
Manifest.permission.CAMERA,
Manifest.permission.RECORD_AUDIO
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Initialize the GoCoder SDK
goCoder = WowzaGoCoder.init(getApplicationContext(),"GOSK-XXXX-XXXX-XXXX-XXXX-XXXX");
if (goCoder == null) {
// If initialization failed, retrieve the last error and display it
WZError goCoderInitError = WowzaGoCoder.getLastError();
Toast.makeText(this,
"GoCoder SDK error: " +goCoderInitError.getErrorDescription(),
Toast.LENGTH_LONG).show();
return;
}
// Associate the WZCameraView defined in the U/I layout with thecorresponding class member
goCoderCameraView = (WZCameraView) findViewById(R.id.camera_preview);
// Create an audio device instance for capturing and broadcasting audio
goCoderAudioDevice = new WZAudioDevice();
// Create a broadcaster instance
goCoderBroadcaster = new WZBroadcast();
// Create a configuration instance for the broadcaster
goCoderBroadcastConfig= new WZBroadcastConfig(WZMediaConfig.FRAME_SIZE_1920x1080);
// Set the connection properties for the target Wowza Streaming Engineserver or Wowza Cloud account
goCoderBroadcastConfig.setHostAddress("live.someserver.net");
goCoderBroadcastConfig.setPortNumber(1935);
goCoderBroadcastConfig.setApplicationName("live");
goCoderBroadcastConfig.setStreamName("myStream");
// Designate the camera preview as the video broadcaster
goCoderBroadcastConfig.setVideoBroadcaster(goCoderCameraView);
// Designate the audio device as the audio broadcaster
goCoderBroadcastConfig.setAudioBroadcaster(goCoderAudioDevice);
// Associate the onClick() method as the callback for the broadcastbutton's click event
Button broadcastButton = (Button) findViewById(R.id.broadcast_button);
broadcastButton.setOnClickListener(this);
}
//
// Called when an activity is brought to the foreground
//
@Override
protected void onResume() {
super.onResume();
// If running on Android 6 (Marshmallow) or above, check to see if thenecessary permissions
// have been granted
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mPermissionsGranted = hasPermissions(this, mRequiredPermissions);
if (!mPermissionsGranted)
ActivityCompat.requestPermissions(this, mRequiredPermissions,PERMISSIONS_REQUEST_CODE);
} else
mPermissionsGranted = true;
// Start the camera preview display
if (mPermissionsGranted && goCoderCameraView != null) {
if (goCoderCameraView.isPreviewPaused())
goCoderCameraView.onResume();
else
goCoderCameraView.startPreview();
}
}
//
// Callback invoked in response to a call toActivityCompat.requestPermissions() to interpret
// the results of the permissions request
//
@Override
public void onRequestPermissionsResult(int requestCode, Stringpermissions[], int[] grantResults) {
mPermissionsGranted = true;
switch (requestCode) {
case PERMISSIONS_REQUEST_CODE: {
// Check the result of each permission granted
for(int grantResult : grantResults) {
if (grantResult != PackageManager.PERMISSION_GRANTED) {
mPermissionsGranted = false;
}
}
}
}
}
//
// Utility method to check the status of a permissions request for anarray of permission identifiers
//
private static boolean hasPermissions(Context context, String[]permissions) {
for(String permission : permissions)
if (context.checkCallingOrSelfPermission(permission) !=PackageManager.PERMISSION_GRANTED)
return false;
return true;
}
//
// The callback invoked when the broadcast button is pressed
//
@Override
public void onClick(View view) {
//return if the user hasn't granted the app the necessary permissions
if (!mPermissionsGranted) return;
// Ensure the minimum set of configuration settings have been specifiednecessary to
// initiate a broadcast streaming session
WZStreamingError configValidationError =goCoderBroadcastConfig.validateForBroadcast();
if (configValidationError != null) {
Toast.makeText(this, configValidationError.getErrorDescription(),Toast.LENGTH_LONG).show();
} else if (goCoderBroadcaster.getStatus().isRunning()) {
// Stop the broadcast that is currently running
goCoderBroadcaster.endBroadcast(this);
} else {
// Start streaming
goCoderBroadcaster.startBroadcast(goCoderBroadcastConfig, this);
}
}
//
// The callback invoked upon changes to the state of the steamingbroadcast
//
@Override
public void onWZStatus(final WZStatus goCoderStatus) {
// A successful status transition has been reported by the GoCoder SDK
final StringBuffer statusMessage = new StringBuffer("Broadcaststatus: ");
switch (goCoderStatus.getState()) {
case WZState.STARTING:
statusMessage.append("Broadcast initialization");
break;
case WZState.READY:
statusMessage.append("Ready to begin streaming");
break;
case WZState.RUNNING:
statusMessage.append("Streaming is active");
break;
case WZState.STOPPING:
statusMessage.append("Broadcast shutting down");
break;
case WZState.IDLE:
statusMessage.append("The broadcast is stopped");
break;
default:
return;
}
// Display the status message using the U/I thread
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, statusMessage,Toast.LENGTH_LONG).show();
}
});
}
//
// The callback invoked when an error occurs during a broadcast
//
@Override
public void onWZError(final WZStatus goCoderStatus) {
// If an error is reported by the GoCoder SDK, display a message
// containing the error details using the U/I thread
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this,
"Streaming error: " +goCoderStatus.getLastError().getErrorDescription(),
Toast.LENGTH_LONG).show();
}
});
}
//
// Enable Android's sticky immersive full-screen mode
//
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
View rootView =getWindow().getDecorView().findViewById(android.R.id.content);
if (rootView != null)
rootView.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}
}
Wowza Streaming Engine 4是業(yè)界功能強(qiáng)大、API接口豐富的流媒體Server產(chǎn)品,采用它作為流媒體服務(wù)器產(chǎn)品的案例很多,直播、在線教育、IPTV都有它的用武之地。
京ICP備09015132號-996 | 違法和不良信息舉報(bào)電話:4006561155
© Copyright 2000-2026 北京哲想軟件有限公司版權(quán)所有 | 地址:北京市海淀區(qū)西三環(huán)北路50號豪柏大廈C2座11層1105室
北京哲想軟件集團(tuán)旗下網(wǎng)站:哲想軟件 | 哲想動畫