zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    Shared Memory in Windows NT
    Layered Memory Management in Win32
    软件项目管理的75条建议
    Load pdbs when you need it
    Stray pointer 野指针
    About the Rebase and Bind operation in the production of software
    About "Serious Error: No RTTI Data"
    Realizing 4 GB of Address Space[MSDN]
    [bbk4397] 第1集 第一章 AMS介绍
    [bbk3204] 第67集 Chapter 17Monitoring and Detecting Lock Contention(00)
  • 原文地址:https://www.cnblogs.com/vipstone/p/7736577.html
Copyright © 2011-2022 走看看