首页 文章 精选 留言 我的

精选列表

搜索[react-native],共268篇文章
优秀的个人博客,低调大师

react-native trampoline实现

ReactNative有Profiler的功能,能计算每个函数的执行耗时。为了尽量减少测量代码对函数本身执行的影响,ReactNative采用汇编实现Trampoline来实现该功能。本文主要记录该部分核心代码的解读,顺便记录阅读汇编代码的一些技巧。 关键字 arm指令查询地址 arm64调用约定 pseudo-ops 什么是Trampoline Trampoline通常都和跳转相关。本文提到的Trampoline是一个特定的地址,该地址指向特定的功能,待功能执行完毕之后,立马跳出Trampoline回到正常执行路径。 就跟蹦床(英文名:Trampoline)一样,一直在bouncing。 代码实现 ReactNative的Trampoline都是纯手工汇编实现的。因为iOS真机有armv7s、arm64等架构,模拟器有i386、x86_64架构,

优秀的个人博客,低调大师

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 如果本文对你有所帮助,请打赏——1元就足够感动我:) 联系邮箱:intdb@qq.com 我的GitHub: https://github.com/vipstone 关注公众号: 作者: 王磊 出处: http://vipstone.cnblogs.com/ 本文版权归作者和博客园共有,欢迎转载,请标明出处。

优秀的个人博客,低调大师

react-native多图选择、图片裁剪(支持ad/ios图片个数控制)

前言: 目前关于rn比较知名并且封装好的图片选择控件很多,不过能同时支持多图片上传,个数控制兼容iOS/Ad的却寥寥无几,而今天介绍的这款框架可以实现:图片裁剪、最大图片个数限制、拍照、本地相册等功能。 效果: 使用简介: 原理:react-native-syan-image-picker多图片选择器: Android 基于 PictureSelector 2.0 iOS 基于 TZImagePickerController 1.9.0 iOS/android配置:具体步骤参考:https://github.com/syanbo/react-native-syan-image-picker 核心代码: import ImagePicker from 'react-native-syan-image-picker' /** * 默认参数 */ const options = { imageCount: 6, // 最大选择图片数目,默认6 isCamera: true, // 是否允许用户在内部拍照,默认true isCrop: false, // 是否允许裁剪,默认false CropW: ~~(width * 0.6), // 裁剪宽度,默认屏幕宽度60% CropH: ~~(width * 0.6), // 裁剪高度,默认屏幕宽度60% isGif: false, // 是否允许选择GIF,默认false,暂无回调GIF数据 showCropCircle: false, // 是否显示圆形裁剪区域,默认false showCropFrame: true, // 是否显示裁剪区域,默认true showCropGrid: false // 是否隐藏裁剪区域网格,默认false }; /** * 以Callback形式调用 * 1、相册参数暂时只支持默认参数中罗列的属性; * 2、回调形式:showImagePicker(options, (err, selectedPhotos) => {}) * 1)选择图片成功,err为null,selectedPhotos为选中的图片数组 * 2)取消时,err返回"取消",selectedPhotos将为undefined * 按需判断各参数值,确保调用正常,示例使用方式: * showImagePicker(options, (err, selectedPhotos) => { * if (err) { * // 取消选择 * return; * } * // 选择成功 * }) * * @param {Object} options 相册参数 * @param {Function} callback 成功,或失败回调 */ /** * 以Promise形式调用 * 1、相册参数暂时只支持默认参数中罗列的属性; * 2、使用方式 * 1)async/await * handleSelectPhoto = async () => { * try { * const photos = await SYImagePicker.asyncShowImagePicker(options); * // 选择成功 * } catch (err) { * // 取消选择,err.message为"取消" * } * } * 2)promise.then形式 * handleSelectPhoto = () => { * SYImagePicker.asyncShowImagePicker(options) * .then(photos => { * // 选择成功 * }) * .catch(err => { * // 取消选择,err.message为"取消" * }) * } * @param {Object} options 相册参数 * @return {Promise} 返回一个Promise对象 */ 小技巧:iOS拍照为英文,如果需要设置成中文简体,请看这篇:《iOS设置拍照retake和use按钮为中文简体》 到此已经结束了,总体来说使用还是很方便的,如有使用上的问题或者疑问欢迎评论留言~ 如果本文对你有所帮助,请打赏——1元就足够感动我:) 联系邮箱:intdb@qq.com 我的GitHub: https://github.com/vipstone 关注公众号: 作者: 王磊 出处: http://vipstone.cnblogs.com/ 本文版权归作者和博客园共有,欢迎转载,请标明出处。

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册