react-native绑定优酷SDK-附效果图和源码

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏三流程序员的挣扎

Android 单元测试 Robolectric

通过实现一套 JVM 能够运行的 Android 代码,从而实现脱离 Android 环境进行测试。

2483
来自专栏潇涧技术专栏

Head First Android SwipeRefreshLayout

本文内容和代码参考自Implementing Swipe to Refresh, an Android Material Design UI Pattern,原...

1072
来自专栏上善若水

010android初级篇之Activity的返回值

使用startActivity方式启动的Activity和它的父Activity无关,当它关闭时也不会提供任何反馈。 但是使用startActivityFor...

1894
来自专栏俞其荣的博客

Android Architecture Component之Lifecycle解析HeaderLifecyclePart 1Part 2Part 3Footer

终于到了最后的关头,Android Architecture Component 系列的最后一节内容。今天给大家带来的就是 Lifecycle 的解析。

1704
来自专栏androidBlog

Android 自定义 MarqueeView 实现跑马灯 —— 原理篇

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gdutxiaoxu/article/details/...

1801
来自专栏何俊林

Android支付实践(二)之微信支付详解与Demo

前言:集成支持宝和微信支付,是公司获取收益的最主要的部分,这两大巨头几乎在支付业务上不可或缺,今天看下Simon_Crystin独家授权本公众号发步的Andro...

2416
来自专栏Android 开发学习

PagerAdapter闪屏坑的修复

3182
来自专栏Jack的Android之旅

React Native与Android 原生通信

我们用React Native 做混合开发的时候免不了要原生和React Native 进行通信交互,这篇文章就是分享原生模块与JS传递数据的几种方式。

2063
来自专栏Android开发指南

2.抽取代码(BaseActivity)

3588
来自专栏码匠的流水账

聊聊spring cloud gateway的SetStatusGatewayFilter

本文主要研究下spring cloud gateway的SetStatusGatewayFilter

1331

扫码关注云+社区

领取腾讯云代金券