8

Regarding this question, I've been trying to get this done via native modules in Android.

I've declared my Module at .../java/com/myproject/multiplecamerastream following the example at React Native ToastModule (functionality here is not important):

public class MultipleCameraStreamModule extends ReactContextBaseJavaModule {

  private static final String CAMERA_FRONT = "SHORT";
  private static final String CAMERA_BACK = "LONG";

  public MultipleCameraStreamModule(ReactApplicationContext reactContext) {
    super(reactContext);
  }

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

  @Override
  public Map<String, Object> getConstants() {
    final Map<String, Object> constants = new HashMap<>();
    constants.put(CAMERA_FRONT, Toast.LENGTH_SHORT);
    constants.put(CAMERA_BACK, Toast.LENGTH_LONG);
    return constants;
  }

  @ReactMethod
  public void show(String message, int duration) {
    Toast.makeText(getReactApplicationContext(), message, duration).show();
  }
}

Then, my module packager:

public class MultipleCameraStreamPackage 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 MultipleCameraStreamModule(reactContext));
    return modules;
  }
}

I've been able to register it and to make it work. However, it only calls to a Toast in Android (no layout involved).

I'd like to set a layout, so when I call <MultipleCameraStream /> in JSX it renders a native Android layout, like the following:

/* .../multiplecamerastream/MultipleCameraStreamLayout.xml */
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical"
>
    <TextView android:id="@+id/multipleCameraText"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:text="Hello, I am a TextView" 
    />
    <Button android:id="@+id/multipleCameraButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello, I am a Button" 
    />
</LinearLayout>

How can I make that layout to be invoked from my module scripts (MultipleCameraStreamModule), and how can I make reference to its elements so I can interact with them from the Android module side programatically?

Thank you.

Unapedra
  • 1,649
  • 2
  • 20
  • 33

1 Answers1

16

There's explanation in the RN Native UI website itself, but I got lost in it too. :(

But here goes, let me know if there's improvement needed on this:

1) Create a View that will inflate your xml MultipleCameraStreamLayout.xml. Ideally, this CustomView can be used in Android pure code.

public class CustomView extends LinearLayout {
 private Context context;
 public CustomView(Context context) {
   super(context);//ADD THIS
   this.context = context;
 }
 ..
 public void init() {
   //modified here.
    inflate(context, R.layout.xxxxxxxxx, this);
  ...

2) Once set, put this into another class(View Manager) extending SimpleViewManager. Sample:

public class MyCustomReactViewManager extends SimpleViewManager<CustomView> {
   public static final String REACT_CLASS = "MyCustomReactViewManager";

   @Override
   public String getName() {
     return REACT_CLASS;
   }

   @Override
   public CustomView createViewInstance(ThemedReactContext context) {
     return new CustomView(context); //If your customview has more constructor parameters pass it from here.
   }

3) Now add it into the React package createViewManager method, you have created it in MultipleCameraStreamPackage. So, it'll be:

@Override
public List<ViewManager> createViewManagers(
        ReactApplicationContext reactContext) {
    return Arrays.<ViewManager>asList(
            new MyCustomReactViewManager() //Add here.
    );
}

4) You can now use the Android code, by reinstalling it

react-native run-android

5) Expose it in javascript. Create some file CustomView.js

import {requireNativeComponent, ViewPropTypes} from 'react-native';
//
module.exports = requireNativeComponent('MyCustomReactViewManager', null); //Add props are bit different.

6) Start using it into your views. Eg.

import CustomView from './CustomView.js';
...
render() {
 return 
  ...
  <CustomView style={{height:200, width:200}}/>
  ...;
}

Hope this helps.

If you need a code sample it's uploaded here.

Han
  • 453
  • 3
  • 11
  • Thank you! I'll give it a try! – Unapedra Dec 13 '17 at 11:01
  • I've tried it, but I get an error on compiling because `no suitable constructor found for LinearLayout(no arguments) > public MultipleCameraStreamView(Context context) extends LinearLayout`. Also, on React tutorial it says to add the ViewManager to `List createViewManagers`, while you have written it into `List createNativeModules`. In which one of them do I have to add it? Thank you!! – Unapedra Dec 13 '17 at 11:38
  • Ok! The error with `LinearLayout` is solved if I call `super(context);` at its constructor! – Unapedra Dec 13 '17 at 11:49
  • 1
    To your questions: 1) Yes, the super(context); 2) Apologies add to the createViewManagers instead. I guess there's many mistake written esp: the height/width should stay at 200 too. Anyway, for more reference I've created a sample. Feel free to have a look, mind those ugly package naming. https://github.com/yoonghan/RN_Android_Native – Han Dec 13 '17 at 17:50
  • @Han: I have read the code of your project, the problem what I have to start is an intent that calls a class that extends AppCompatActivity. But I'm having doubts. Can I ask you some advice? – Paul Sep 06 '18 at 23:46
  • @Paul sorry for the late reply. I think your question are basically to get an Activity working. Those examples I know and had are only view and components but never an activity, sadly. – Han Sep 10 '18 at 14:12
  • @Paul your need is definitely to start a new activity. I have not tried but this may lead you a direction..https://stackoverflow.com/questions/42253397/call-android-activity-from-react-native-code – Han Sep 10 '18 at 14:22
  • @Han I can contact you privately I'm having problems, especially with the installation of a native android dependency in order to create a bridge for react-native. – Paul Sep 12 '18 at 22:17