2019-05-07 14:32:33 Wangdanting123 阅读数 498
  • 完全征服React Native

    React Native是Facebook于2015年推出的跨平台开发工具,可用于开发Android和iOS App,并且同时具有混合开发的优点(热更新,跨平台)以及本地App的性能。 本课程采用新的ES6开发,主要内容包括ReactNative的基础知识,ReactNative的布局,组件,API,封装本地API和组件,发布ReactNative App,本地与ReactNative深度结合

    57472 人正在学习 去看看 李宁
import React, { PureComponent } from 'react';
import { Text, TouchableOpacity, Linking, Alert } from 'react-native';
import { Toast } from '@ant-design/react-native';

class Contact extends PureComponent {
  /**
   *  拨打电话
   * @param {string} phone 版本号
   * @example
   * call('18888888888')
   */
  call = phone => {
    const url = `tel:${phone}`;
    Linking.canOpenURL(url)
      .then(supported => {
        if (!supported) {
          return Alert.alert('提示', `您的设备不支持该功能,请手动拨打 ${phone}`, [
            { text: '确定' }
          ]);
        }
        return Linking.openURL(url);
      })
      .catch(err => Toast.info(`出错了:${err}`, 1.5));
  };

  callMerchant = () => {
    this.call('18888888888');
  };

  render() {
    return (
      <TouchableOpacity onPress={this.callMerchant}>
        <Text>联系商家</Text>
      </TouchableOpacity>
    );
  }
}

export default Contact;

 

2017-08-27 19:39:03 vitamio 阅读数 362
  • 完全征服React Native

    React Native是Facebook于2015年推出的跨平台开发工具,可用于开发Android和iOS App,并且同时具有混合开发的优点(热更新,跨平台)以及本地App的性能。 本课程采用新的ES6开发,主要内容包括ReactNative的基础知识,ReactNative的布局,组件,API,封装本地API和组件,发布ReactNative App,本地与ReactNative深度结合

    57472 人正在学习 去看看 李宁

React Native 调用原生Android、iOS模块实现拨号功能

一 前言

由于前几个月公司2.0项目开发技术选型为React Native,技术部相关人员开始学习React Native相关的技术,笔者是一名Android开发者,下文所描述的React Native调用Android/iOS模块中关于iOS的部分如有误的地方,请指出。为了让从Android或iOS学习React Native的同志更加清楚的了解另一移动端,笔者尽可能写的详细点。

二 效果

下面两张图分别为iOS和Android上效果图,其中iOS效果图中点击电话号码会打印log,并不会调起iOS拨号界面,因为iOS模拟器不支持此功能,所以要想看效果只能用真机查看。这里打印log是为了证明React Native成功调起了原生iOS模块功能。

react native调用ios

React Native调用Android

三 实现方案

关于调用拨号功能以及调用浏览器、短信、邮箱等功能,可有两种实现方案。

一种是按照React Native提供的调用原生的过程方案来调用,这种适合大部分React Native调用原生功能的需求,掌握这种后,基本以后再有调用原生需求即可按照此过程方案解决,此文也会选用这种方案进行描述。

另一种是React Native帮我们封装的Linking模块可以实现这类的需求,这种相比上一种来说相对简单,主要适用于调用原生的电话、短信、邮箱、浏览器等功能。

四 实现原生Android模块

1.在自己新建的Reacat Native项目中android/app/src/main/java/xxx(项目包名)/ 目录下(为了和其他文件分离,笔者又在此目录下新建一个native文件夹),需要新建一个java类文件,例如文件名为CallPhoneModule.java,这个java类一定要继承RN提供的ReactContextBaseJavaModule抽象类,然后实现其构造函数,其中的参数要为ReactApplicationContext reactContext。

public class CallPhoneModule extends ReactContextBaseJavaModule {
    public CallPhoneModule(ReactApplicationContext reactContext) {
        super(reactContext);
    }
 }

这里写图片描述

2.然后实现NativeModule中定义的getName()方法,返回一个String类型字符串,这个返回结果将要在JavaScript中使用,例如返回“CallPhoneModule”,则可以在JavaScript中通过React.NativeModules.CallPhoneModule调用。注意,如果返回的字符串中有RCT前缀,则会自动移除RCT前缀。例如返回“RCTCallPhoneModule”,则在JavaScript中依然可以通过React.NativeModules.CallPhoneModule调用。CallPhoneModule继承ReactContextBaseJavaModule,ReactContextBaseJavaModule继承BaseJavaModule,BaseJavaModule实现了NativeModule接口,这是CallPhoneModule与NativeModule的关系。

 @Override
    public String getName() {
        return "CallPhoneModule";
    }

3.然后在CallPhoneModule类中写一个方法,这个方法提供给JavaScript调用,例如方法名为callPhone,里面传递String类型参数(非必须),特别的这个方法要使用@ReactMethod注解,以及返回类型必须为void。然后在callPhone方法中写入要实现的功能,这里写入了拨号功能的实现。

 Intent intent = new Intent(Intent.ACTION_DIAL,  Uri.parse("tel:" + phoneString));
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        this.reactContext.startActivity(intent);

CallPhoneModule.java文件的全部代码如下:

package com.zhuku02;

import android.content.Intent;
import android.net.Uri;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import java.lang.String;

public class CallPhoneModule extends ReactContextBaseJavaModule {

    public ReactApplicationContext reactContext;

    public CallPhoneModule(ReactApplicationContext reactContext) {
        super(reactContext);
        this.reactContext = reactContext;
    }

    @ReactMethod
    public void callPhone(String phoneString) {
        Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + phoneString));
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        this.reactContext.startActivity(intent);
    }

    @Override
    public String getName() {
        return "CallPhoneModule";
    }
}

这里写图片描述

4.新建一个java类文件,例如文件名为CallPhoneReactPackage.java,这个类必须实现ReactPackage接口,然后实现createViewManagers、createNativeModules两个方法,特别的要在createNativeModules方法的返回值中add进刚才新建的CallPhoneModule类。

CallPhoneReactPackage.java全部代码如下:

package com.zhuku02;

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import com.zhuku02.CallPhoneModule;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class CallPhoneReactPackage implements ReactPackage {

    @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }

    @Override
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
        List<NativeModule> modules = new ArrayList<>();

        modules.add(new CallPhoneModule(reactContext));

        return modules;
    }
}

这里写图片描述

5.最后在MainApplication.java文件中的getPackages方法中加上刚才新建的CallPhoneReactPackage类。至此,原生Android模块书写完毕。关于JavaScript调用原生Android模块代码会在文末和调用原生iOS一起写出。

修改后的MainApplication.java文件代码如下:

package com.zhuku02;

import android.app.Application;
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
import com.facebook.soloader.SoLoader;

import com.zhuku02.CallPhoneReactPackage;

import java.util.Arrays;
import java.util.List;


public class MainApplication extends Application implements ReactApplication {

    private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
        @Override
        public boolean getUseDeveloperSupport() {
            return BuildConfig.DEBUG;
        }

        @Override
        protected List<ReactPackage> getPackages() {
            return Arrays.<ReactPackage>asList(
                    new MainReactPackage(),
                    new CallPhoneReactPackage()
            );
        }
    };

    @Override
    public ReactNativeHost getReactNativeHost() {
        return mReactNativeHost;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        SoLoader.init(this, /* native exopackage */ false);
    }
}

这里写图片描述

五 实现原生iOS模块

1.在自己新建的Reacat Native项目中ios/xxx(项目包名)/ 目录下,需要新建一个后缀为m和一个后缀为h的文件。为了和其他文件分离以及和Android保持一致,笔者又在此目录下新建一个native文件夹。在Xcode的此文件夹上右键New File,然后在弹出的页面中Cocoa Touch Class选项输入文件名,这样会建立出相同文件名的m和h文件。如果New File时,分别选择Objective-C File和Header File,则这两个文件名要相同。例如文件名称为CallPhoneModuleIos。

2.在CallPhoneModuleIos.h文件中,类要实现RN提供的RCTBridgeModule协议。RCT是ReaCT的缩写,React Native中Object-C相关的命名均以RCT开头。RCTBridgeModule是定义好的protocol,实现该协议的类,会自动注册到Object-C对应的Bridge中。Object-C Bridge上层负责与Object-C通信,下层负责和JavaScript Bridge通信,而JavaScript Bridge负责和JavaScript通信。这样,通过Object-C Bridge和JavaScript Bridge就可以实现JavaScript和Object-C的相互调用。

CallPhoneModuleIos.h文件如下:


#import <UIKit/UIKit.h>
#import <React/RCTBridgeModule.h>
#import <React/RCTLog.h>

@interface CallPhoneModuleIos : NSObject <RCTBridgeModule>

@end

这里写图片描述

3.CallPhoneModuleIos.m文件中,类需要包含RCT_EXPORT_MODULE()宏,作用是自动注册一个module。这个宏可以添加一个参数,用来指定在JavaScript调用这个模块的名字,类似于上文中说的getName()方法。如果不添加这个参数,则默认就是这个类的名字。

4.然后需要在此类中写一个方法,提供给RN调用,方法通过RCT_EXPORT_METHOD()宏来实现。

RCT_EXPORT_METHOD(callPhone: (NSString *)phone){
   NSLog(@"======%@",phone);
}

CallPhoneModuleIos.m完整代码:

#import "CallPhoneModuleIos.h"
#import <Foundation/Foundation.h>

@implementation CallPhoneModuleIos

RCT_EXPORT_MODULE(CallPhoneModuleIos);

RCT_EXPORT_METHOD(callPhone: (NSString *)phone){

   NSLog(@"======%@",phone);
  //去掉注释,下面代码就是实现拨号功能代码,但还未真机测试
//  NSMutableString * str = [[NSMutableString alloc] initWithFormat:@"telprompt://%@",phone];
//  [[UIApplication sharedApplication] openURL:[NSURL URLWithString:str]];

}

// -(dispath_queue_t)methodQueue{
//     return dispath_get_main_queue();
// }

@end

这里写图片描述

至此,则原生iOS代码书写完成,现在即将开始调用。

六 React Native调用Android、iOS原生模块

为了在JavaScript端同时访问Android、iOS原生模块更加方便,笔者把原生模块的调用封装在一个JavaScript文件中,这样在需要调用的地方直接调用此JavaScript文件既可,同时在此文件中,处理好Android、iOS、Web(若有)的分别调用。

import {Platform, NativeModules} from 'react-native';

var module = null;
if (Platform.OS == 'ios') {
    module = NativeModules.CallPhoneModuleIos;
} else if (Platform.OS == 'android') {  
    module = NativeModules.CallPhoneModule;
} else if (Platform.OS == 'web') {
    //暂未实现web功能  
}
export default module;

这里写图片描述

然后在JavaScript文件中这样调用:

import CallPhone from '../../native/CallPhone';
  CallPhone.callPhone('4007773177');

到这里,整篇文章就结束了,疑问、建议或者指教欢迎讨论。

七 参考资料

native-modules-ios
native-modules-android

原创文章,来自于Vitamio,转载请注明出处。

2015-12-03 14:21:19 u013148839 阅读数 5419
  • 完全征服React Native

    React Native是Facebook于2015年推出的跨平台开发工具,可用于开发Android和iOS App,并且同时具有混合开发的优点(热更新,跨平台)以及本地App的性能。 本课程采用新的ES6开发,主要内容包括ReactNative的基础知识,ReactNative的布局,组件,API,封装本地API和组件,发布ReactNative App,本地与ReactNative深度结合

    57472 人正在学习 去看看 李宁

React Native 实现原生模块 实现拨打电话功能


Android js可用标签 IntentAndroid(0.16+)
IOS 可用 LinkingIOS

参考 API :http://react-native.cn/docs/native-modules-android.html#content

在onCreate 中

           mReactInstanceManager = ReactInstanceManager.builder()
            .addPackage(new SpringBoardPackages())

添加模块
我们首先来创建一个原生模块。一个原生模块是一个继承了ReactContextBaseJavaModule的Java类,它可以实现一些JavaScript所需的功能。我们这里的目标是让我们可以在JavaScript里写ToastAndroid.show(‘Awesome’, ToastAndroid.SHORT);,来调起一个Toast通知。

   private class SpringBoard extends ReactContextBaseJavaModule {
        Context context;
        public SpringBoard(ReactApplicationContext reactContext) {
            super(reactContext);
        }
        @ReactMethod
        public void gotoIMS(String number) {
            //用intent启动拨打电话
            Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + number));
            MainActivity.this.startActivity(intent);
        }
        @Override
        public String getName() {
            return "SpringBoard";
        }
    }

定义内部类
我们需要在你的应用的Package类的createNativeModules方法中添加这个模块。如果一个模块没有被注册,它从JavaScript中也无法访问到。

 // 实现跳转功能
    private class SpringBoardPackages implements ReactPackage {
        @Override
        public List<NativeModule> createNativeModules(ReactApplicationContext context) {
            List<NativeModule> modules = new ArrayList<>();

            modules.add(new SpringBoard(context));
            return modules;
        }

        @Override
        public List<Class<? extends JavaScriptModule>> createJSModules() {
            return Collections.emptyList();
        }

        @Override
        public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
            return null;
        }
    }

最后在js 中

var {
  //  添加 
NativeModules,
} = React;

    //调用模块方法
  var SpringBoard = NativeModules.SpringBoard;
        // 跳转到 IM 模块
        SpringBoard.gotoIMS("13696891101");

Demo 下载地址

2015-07-21 09:26:57 yeyuehunluhongyu 阅读数 1056
  • 完全征服React Native

    React Native是Facebook于2015年推出的跨平台开发工具,可用于开发Android和iOS App,并且同时具有混合开发的优点(热更新,跨平台)以及本地App的性能。 本课程采用新的ES6开发,主要内容包括ReactNative的基础知识,ReactNative的布局,组件,API,封装本地API和组件,发布ReactNative App,本地与ReactNative深度结合

    57472 人正在学习 去看看 李宁

一、项目介绍

基于React-Native & Node通讯录App

(1)主要完成的功能有:

  • 基于文件系统的Node.js服务端;
  • 通讯录功能(分类页 + 列表页 + 拨号邮箱邮件)
  • 公告功能(列表页 + 详情页)
  • 通讯录和内容管理功能
  • webview内嵌实例 效果如下图所示:
 
 
 

(2)安装启动程序

(1)首先进入address_book目录安装node module;命令行:$ npm install 
(2)其次cd server,启动node数据接口服务,命令行: $ node app.js
(3)初次登录用户名:test@126.com    密码:123

(3)Tip:

(1)为了演示,代码有些粗糙;     
(2)服务端也不是很完善,为了方便快速搭建,使用的是基于node的文件服务。
(3)oschina会同步更新改项目:https://git.oschina.net/vczero/React-Native-App
(4)相关入门教程:https://github.com/vczero/react-native-lession

为了省点篇幅,将第七篇文章也附到下面吧:

React-Native入门指南

第七篇动手写组件

React-Native的核心思想就是组件化,相当于MVC的view,因此开发应用的最佳方式就是将功能组件化。

一、最简单的方式

这里我们实现一个最简单的组件,就是邮件的末尾署名的组件。组件意味着复用,意味着统一。现在有这样一个需求,我们需要根据不同用户发送邮件时,生成每个用户的名片(即邮件末尾的署名)。

1、一般一开始的实现方式如下,直接将组件内容写到功能需求的地方:
<View>
    <View>..........这里是当前邮件组的其它功能</View>
    <View>
        <Text>框架研发部</Text>
        <Text>www.ctrip.com</Text>
    </View>
</View>

2、有一天,其它的部门的同事提出他们也需要在其他的地方,增加他们的邮件署名,那么你是否又会复制一份代码呢,当然不是,我们可以组件化:
var Email = React.createClass({
    render: function(){
        return (
            <View style={styles.container}>
                <Text style={styles.text}>{this.props.name}</Text>
                <Text style={styles.text}>{this.props.url}</Text>
            </View>
        );
    }
});

3、整体的代码如下:

二、循环一个文章列表

要实现的效果如下图:

第一步改造我们的组件
var Article = React.createClass({
    render: function(){
        return (
            <View style={styles.container}>
                <Text style={[styles.text, styles.title]}>{this.props.title}</Text>
                <Text style={styles.text}>{this.props.author}</Text>
                <Text style={styles.text}>{this.props.time}</Text>
            </View>
        );
    }
});

第二步定义数据model和循环
var App = React.createClass({
    getInitialState: function(){
        var data = [
        {
            title: "React-Native入门指南",
            author: "vczero",
            time: "2015-06-28"
        },
        {
            title: "为什么世界不一样",
            author: "vczero",
            time: "2015-06-8"
        },
        {
            title: "你来,我就告诉你",
            author: "vczero",
            time: "2015-04-01"
        }
    ];
    return {
        articles: data
    };
},
render: function(){
    return(
        <ScrollView>
        {this.state.articles.map(function(article){
        return <Article title={article.title} author={article.author} time={article.time}/>
        })}
    </ScrollView>
    );
    }
});

整个代码如下:

2016-09-18 18:30:12 micsay 阅读数 1530
  • 完全征服React Native

    React Native是Facebook于2015年推出的跨平台开发工具,可用于开发Android和iOS App,并且同时具有混合开发的优点(热更新,跨平台)以及本地App的性能。 本课程采用新的ES6开发,主要内容包括ReactNative的基础知识,ReactNative的布局,组件,API,封装本地API和组件,发布ReactNative App,本地与ReactNative深度结合

    57472 人正在学习 去看看 李宁
//Linking为RN自带的组件
   let url = "mqqwpa://im/chat?chat_type=wpa&uin=QQ号";//调用QQ
   //let url = "tel: 电话号码";//调用拨号
   Linking.canOpenURL(url).then(supported => {
       if (supported) {
           Linking.openURL(url);
       }
   });
没有更多推荐了,返回首页