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