ReactNative綁定優酷SDK需要用到兩部分知識:
- 優酷本身的sdk綁定;
- RN與原生界面的交互;
效果:
RN版本:0.49.3
代碼更新日期:2017.10.26
下文也根據綁定需要分為兩部分:
一、優酷sdk綁定;
二、RN與原生頁面的交互;
一、優酷SDK綁定
1.優酷雲平台創建應用,獲取到client_id和client_secret;
申請地址:http://cloud.youku.com/app
如圖:
2.引入sdk:
在目錄app/libs加入優酷sdk:mma_sdk.jar、utdid4all-1.1.5.5.jar、YoukuPlayerOpenSDK-release.aar,sdk下載地址:http://cloud.youku.com/down/play
在目錄app/build.gradle里面添加下面兩段配置:
android { // ... 之前本身配置,下面為添加的配置 //添加libs目錄配置 repositories { flatDir { dirs 'libs' } } sourceSets { main { jniLibs.srcDirs = ['libs']; } } } dependencies { // ... 之前本身配置,下面為添加的配置 //公共庫 compile 'com.alibaba:fastjson:1.1.56.android' compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.5' //sdk compile(name: 'YoukuPlayerOpenSDK-release', ext: 'aar') }
3.在MainApplication.java初始化優酷播放代碼:
import com.youku.cloud.player.YoukuPlayerConfig; //請在這里輸入你的應用的clientId,clientSecret public static final String CLIENT_ID_WITH_AD = "e7e4d0ee1591b0bf"; public static final String CLIENT_SECRET_WITH_AD = "1fbf633f8a55fa1bfabf95729d8e259a"; @Override public void onCreate() { super.onCreate(); SoLoader.init(this, /* native exopackage */ false); YoukuPlayerConfig.setClientIdAndSecret(CLIENT_ID_WITH_AD,CLIENT_SECRET_WITH_AD); YoukuPlayerConfig.onInitial(this); YoukuPlayerConfig.setLog(false); }
4.新建Activity和后置類;
頁面代碼:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout 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:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.gangguwang.yewugo.YKPlayerActivity" android:orientation="vertical"> <com.youku.cloud.player.YoukuPlayerView android:id="@+id/baseview" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" > </com.youku.cloud.player.YoukuPlayerView> </LinearLayout>
后置類代碼:
package com.gangguwang.yewugo; import android.content.Intent; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.Toast; import android.text.TextUtils; import com.youku.cloud.player.YoukuPlayerConfig; import com.youku.cloud.player.YoukuPlayerView; import com.youku.cloud.utils.Logger; import com.youku.cloud.module.PlayerErrorInfo; import com.youku.cloud.player.PlayerListener; import com.youku.cloud.player.VideoDefinition; import com.youku.cloud.utils.ValidateUtil; import com.youku.download.DownInfo; public class NativeActivity extends AppCompatActivity { private YoukuPlayerView youkuPlayerView; private String vid="XMzA1NzYwMTQxNg=="; private String password=""; private boolean local = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_native); // Intent mIntent=getIntent(); // if(mIntent!=null) { // Toast.makeText(this,"請求參數:"+mIntent.getStringExtra("params"),Toast.LENGTH_SHORT).show();; // } // Button btn_two=(Button)this.findViewById(R.id.btn_two); // //btn_two.setVisibility(View.GONE); //隱藏按鈕 // btn_two.setOnClickListener(new View.OnClickListener() { // @Override // public void onClick(View v) { // Intent mIntent=new Intent(NativeActivity.this,MainActivity.class); // mIntent.putExtra("data","你是123..."); // NativeActivity.this.startActivity(mIntent); // NativeActivity.this.finish(); // } // }); youkuPlayerView = (YoukuPlayerView)findViewById(R.id.baseview); // 初始化播放器 youkuPlayerView.attachActivity(this); youkuPlayerView.setPreferVideoDefinition(VideoDefinition.VIDEO_HD); youkuPlayerView.setPlayerListener(new MyPlayerListener()); youkuPlayerView.setShowFullBtn(true); autoplayvideo(); } private void autoplayvideo() { if (local) { youkuPlayerView.playLocalVideo(vid); } else { if (TextUtils.isEmpty(password)) { youkuPlayerView.playYoukuVideo(vid); } else { youkuPlayerView.playYoukuPrivateVideo(vid, password); } } } @Override protected void onPause() { super.onPause(); // 必須重寫的onPause() youkuPlayerView.onPause(); } @Override protected void onResume() { super.onResume(); // 必須重寫的onResume() youkuPlayerView.onResume(); } @Override protected void onDestroy() { super.onDestroy(); // 必須重寫的onDestroy() youkuPlayerView.onDestroy(); } // 添加播放器的監聽器 private class MyPlayerListener extends PlayerListener { @Override public void onComplete() { // TODO Auto-generated method stub super.onComplete(); } @Override public void onError(int code, PlayerErrorInfo info) { // TODO Auto-generated method stub //txt1.setText(info.getDesc()); } @Override public void OnCurrentPositionChanged(int msec) { // TODO Auto-generated method stub super.OnCurrentPositionChanged(msec); } @Override public void onVideoNeedPassword(int code) { // TODO Auto-generated method stub super.onVideoNeedPassword(code); } @Override public void onVideoSizeChanged(int width, int height) { // TODO Auto-generated method stub super.onVideoSizeChanged(width, height); } } }
5.配置AndroidManifest.xml
5.1:給你的播放器Activity加上監聽屏幕旋轉的語句
<activity android:name=".NativeActivity" android:configChanges="orientation|keyboard|keyboardHidden|screenSize|screenLayout|uiMode" android:exported="true" android:launchMode="singleTask" />
5.2:添加權限
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" /> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" /> <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
到此,優酷播放的sdk已經配置完畢。
二、RN與原生頁面的互交
使用NativeModules模塊互交,本章分為:
1.RN調用;
2.創建中間交互類IntentModule.java、IntentReactPackage.java;
3.使用反射和Intent進行通知原生界面;
1.RN調用代碼:
<Button onPress={() => { NativeModules.IntentModule.startActivityFromJS('你的包名.NativeActivity', '參數'); }} title=" 播 放 " color="#841584" />
2.創建中間交互類
a).注冊原生模塊類 IntentReactPackage.java 代碼如下:
package com.gangguwang.yewugo; import com.facebook.react.ReactPackage; import com.facebook.react.bridge.JavaScriptModule; import com.facebook.react.bridge.NativeModule; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.uimanager.ViewManager; import java.util.Arrays; import java.util.Collections; import java.util.List; public class IntentReactPackage implements ReactPackage { @Override public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) { return Arrays.<NativeModule>asList( new IntentModule(reactContext) ); } // @Override // public List<Class<? extends JavaScriptModule>> createJSModules() { // return Collections.emptyList(); // } @Override public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) { return Collections.emptyList(); } }
代碼解讀:固定的api固定的方法必須重寫createNativeModules和createViewManagers方法,只是把另一個交互類IntentModule注冊到createNativeModules里面。
b).創建你的RN交互暴露方法類 IntentModule.java,代碼如下:
package com.gangguwang.yewugo; import android.app.Activity; import android.content.Intent; import android.text.TextUtils; import com.facebook.react.bridge.Callback; import com.facebook.react.bridge.JSApplicationIllegalArgumentException; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; public class IntentModule extends ReactContextBaseJavaModule { public IntentModule(ReactApplicationContext reactContext) { super(reactContext); } @Override public String getName() { return "IntentModule"; } /** * Activtiy跳轉到JS頁面,傳輸數據 * @param successBack * @param errorBack */ @ReactMethod public void dataToJS(Callback successBack, Callback errorBack){ try{ Activity currentActivity = getCurrentActivity(); String result = currentActivity.getIntent().getStringExtra("data"); if (TextUtils.isEmpty(result)){ result = "沒有數據"; } successBack.invoke(result); }catch (Exception e){ errorBack.invoke(e.getMessage()); } } /** * 從JS頁面跳轉到原生activity 同時也可以從JS傳遞相關數據到原生 * @param className * @param params */ @ReactMethod public void startActivityFromJS(String className, String params){ try{ Activity currentActivity = getCurrentActivity(); if(null!=currentActivity){ Class toActivity = Class.forName(className); Intent intent = new Intent(currentActivity,toActivity); //intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.putExtra("params", params); currentActivity.startActivity(intent); } }catch(Exception e){ throw new JSApplicationIllegalArgumentException("不能打開Activity : "+e.getMessage()); } } /** * 從JS頁面跳轉到Activity界面,並且等待從Activity返回的數據給JS * @param className * @param params * @param requestCode * @param successBack * @param errorBack */ @ReactMethod public void startActivityFromJSGetResult(String className, String params, int requestCode, Callback successBack, Callback errorBack){ try { Activity currentActivity = getCurrentActivity(); if(currentActivity != null) { Class toActivity = Class.forName(className); Intent intent = new Intent(currentActivity,toActivity); //intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.putExtra("params", params); currentActivity.startActivityForResult(intent,requestCode); // //進行回調數據 // successBack.invoke(MainActivity.mQueue.take()); } } catch (Exception e) { errorBack.invoke(e.getMessage()); e.printStackTrace(); } } // /** // * 必須添加反射注解不然會報錯 // * 這個方法就是ReactNative將要調用的方法,會通過此類名字調用 // * @param msg // */ // @ReactMethod // public void callNativeMethod(String msg) { // Toast.makeText(mContext, msg, Toast.LENGTH_SHORT).show(); // //startActivityForResult(myIntent, 1); // } }
c).在MainApplication.java里面設置交互類IntentReactPackage
@Override protected List<ReactPackage> getPackages() { return Arrays.<ReactPackage>asList( new MainReactPackage(), new IntentReactPackage() ); }
3.使用反射和Intent進行通知原生界面;
在IntentModule已經體現了,核心代碼:
Activity currentActivity = getCurrentActivity(); if(null!=currentActivity){ Class toActivity = Class.forName(className); Intent intent = new Intent(currentActivity,toActivity); intent.putExtra("params", params); currentActivity.startActivity(intent); }
到此為止已經全部大功告成!源碼地址:https://github.com/vipstone/react-native-youku