Run node.js from android java (processing)

Introduction

Have you ever run anything other than java on android? If you just want to run it, you can often do it by using termux or an application for each language, but it is difficult to pack it in an apk and distribute it (I was frustrated about python) However, there are some such as Node.js introduced this time that have some way to work with android due to the wisdom of our predecessors. So let's finish the introduction so far and see how to actually do it

Things necessary

node in android Environment to run java on android

Preparation

Let's put what we need in assets I don't need npm for the time being Put the downloaded file called node in assets / resource / bin Add WriteExternalStorage permission or readExternalStorage permission as appropriate. import At first

import java.io.IOException;
import java.util.Map;
import fi.iki.elonen.*;
import android.content.res.AssetManager;
import android.os.Bundle;
import java.io.*;
import java.util.*;

Please import

Functions to copy from assets to localStorage

Since only files in localStorage can be executed, move them from assets with the copyFiles function.

private boolean isDirectory(final String path) throws IOException { 
  AssetManager assetManager = getActivity().getResources().getAssets();
  boolean isDirectory = false;
  try {
    if (assetManager.list(path).length > 0) {
      isDirectory = true;
    } else {
      assetManager.open(path);
    }
  }
  catch (FileNotFoundException fnfe) {
    isDirectory = true;
  }
  return isDirectory;
}
private void copyFiles(final String parentPath, final String filename, final File toDir) throws IOException {
  AssetManager assetManager = getActivity().getResources().getAssets();
  String assetpath = (parentPath != null ? parentPath + File.separator + filename : filename);
  if (isDirectory(assetpath)) {
    if (!toDir.exists()) {
      toDir.mkdirs();
    } 
    for (String child : assetManager.list(assetpath)) {
      copyFiles(assetpath, child, new File(toDir, child));
    }
  } else {
    copyData(assetManager.open(assetpath), new FileOutputStream(new File(toDir.getParentFile(), filename)));
  }
}
private void copyData(InputStream input, FileOutputStream output) throws IOException {
  int DEFAULT_BUFFER_SIZE = 1024 * 4; 	
  byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; 	
  int n = 0; 		
  while (-1 != (n = input.read(buffer))) { 
    output.write(buffer, 0, n);
  } 		
  output.close(); 		
  input.close();
}

Please change the parts of getContext () and getActivity () to appropriate ones.

Function to call node.js

Call node.js with the adbCommandExe function sketchPath function returns the location of localstorage The addEnv function adds an environment variable

String sketchPath(String path){
  return getContext().getFilesDir().getAbsolutePath()+"/"+path;
}
void addEnv(ProcessBuilder pb,String e,String value){
  Map<String, String> env = pb.environment();
  env.put(e,value);
}
private String adbCommandExe(String command,File dir) {
  StringBuilder suilder = new StringBuilder();
  ProcessBuilder processBuilder = new ProcessBuilder(command.split(" "));
  if(dir!=null)processBuilder.directory(dir);
  addEnv(processBuilder,"LD_LIBRARY_PATH",sketchPath("lib"));
  addEnv(processBuilder,"PATH",sketchPath("bin"));
  addEnv(processBuilder,"LANG","en_US.UTF-8");
  InputStream iStream = null;
  InputStreamReader isReader = null;
  try {
    Process proc = processBuilder.start();
    iStream = proc.getInputStream();
    isReader = new InputStreamReader(iStream);
    BufferedReader bufferedReader = new BufferedReader(isReader);
    String line;
    while ((line = bufferedReader.readLine()) != null) {
      suilder.append(line);
      suilder.append("\n");
      println(line);
    }
    BufferedReader br = new BufferedReader(new InputStreamReader(proc.getErrorStream())); 
    while ((line = br.readLine()) != null) { 
      suilder.append(line);
      suilder.append("\n");
      println(line);
    }
  }
  catch(Exception e) {
    e.printStackTrace();
  } 
  finally {
    try {
      if (iStream != null) {
        iStream.close();
      }
      if (isReader != null) {
        isReader.close();
      }
    } 
    catch(Exception e) {
      e.printStackTrace();
    }
  }
  return suilder.toString();
}

Run

Actually call the function

void run(){
  try {
    copyFiles(null, "resource", new File(sketchPath("")));
  } 
  catch (IOException ioe) { 
    println("copy error");
  }
  for(File file:new File(sketchPath("bin")).listFiles()){
    if (file.setExecutable(true, true))println("a");
  }
  for(File file:new File(sketchPath("lib")).listFiles()){
    if (file.setExecutable(true, true))println("a");
  }
  File dir = new File("/storage/emulated/0/webIDE/temp");
  adbCommandExe("node -v",dir);
}

To put it all together

Try calling the run function when you want to run node.js

void run(){
  try {
    copyFiles(null, "resource", new File(sketchPath("")));
  } 
  catch (IOException ioe) { 
    println("copy error");
  }
  for(File file:new File(sketchPath("bin")).listFiles()){
    if (file.setExecutable(true, true))println("a");
  }
  for(File file:new File(sketchPath("lib")).listFiles()){
    if (file.setExecutable(true, true))println("a");
  }
  File dir = new File("/storage/emulated/0/webIDE/temp");
  adbCommandExe("node -v",dir);
}
String sketchPath(String path){
  return getContext().getFilesDir().getAbsolutePath()+"/"+path;
}
void addEnv(ProcessBuilder pb,String e,String value){
  Map<String, String> env = pb.environment();
  env.put(e,value);
}
private String adbCommandExe(String command,File dir) {
  StringBuilder suilder = new StringBuilder();
  ProcessBuilder processBuilder = new ProcessBuilder(command.split(" "));
  if(dir!=null)processBuilder.directory(dir);
  addEnv(processBuilder,"LD_LIBRARY_PATH",sketchPath("lib"));
  addEnv(processBuilder,"PATH",sketchPath("bin"));
  addEnv(processBuilder,"LANG","en_US.UTF-8");
  InputStream iStream = null;
  InputStreamReader isReader = null;
  try {
    Process proc = processBuilder.start();
    iStream = proc.getInputStream();
    isReader = new InputStreamReader(iStream);
    BufferedReader bufferedReader = new BufferedReader(isReader);
    String line;
    while ((line = bufferedReader.readLine()) != null) {
      suilder.append(line);
      suilder.append("\n");
      println(line);
    }
    BufferedReader br = new BufferedReader(new InputStreamReader(proc.getErrorStream())); 
    while ((line = br.readLine()) != null) { 
      suilder.append(line);
      suilder.append("\n");
      println(line);
    }
  }
  catch(Exception e) {
    e.printStackTrace();
  } 
  finally {
    try {
      if (iStream != null) {
        iStream.close();
      }
      if (isReader != null) {
        isReader.close();
      }
    } 
    catch(Exception e) {
      e.printStackTrace();
    }
  }
  return suilder.toString();
}
private boolean isDirectory(final String path) throws IOException { 
  AssetManager assetManager = getActivity().getResources().getAssets();
  boolean isDirectory = false;
  try {
    if (assetManager.list(path).length > 0) {
      isDirectory = true;
    } else {
      assetManager.open(path);
    }
  }
  catch (FileNotFoundException fnfe) {
    isDirectory = true;
  }
  return isDirectory;
}
private void copyFiles(final String parentPath, final String filename, final File toDir) throws IOException {
  AssetManager assetManager = getActivity().getResources().getAssets();
  String assetpath = (parentPath != null ? parentPath + File.separator + filename : filename);
  if (isDirectory(assetpath)) {
    if (!toDir.exists()) {
      toDir.mkdirs();
    } 
    for (String child : assetManager.list(assetpath)) {
      copyFiles(assetpath, child, new File(toDir, child));
    }
  } else {
    copyData(assetManager.open(assetpath), new FileOutputStream(new File(toDir.getParentFile(), filename)));
  }
}
private void copyData(InputStream input, FileOutputStream output) throws IOException {
  int DEFAULT_BUFFER_SIZE = 1024 * 4; 	
  byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; 	
  int n = 0; 		
  while (-1 != (n = input.read(buffer))) { 
    output.write(buffer, 0, n);
  } 		
  output.close(); 		
  input.close();
}

Afterword

That's all for the explanation of running node.js from android java (processing). Did you do it?

Recommended Posts

Run node.js from android java (processing)
Run a batch file from Java
Notes on Android (java) thread processing
Reintroducing Java 8 available from Android Studio 2.4
Data processing using stream API from Java 8
Calling java from C ++ on Android NDK
Java thread processing
Java string processing
[Java] Multi-thread processing
[Java] Stream processing
java iterative processing
[Android] Call Kotlin's default argument method from Java
Run Rust from Java with JNA (Java Native Access)
Run R from Java I want to run rJava
[Android / Java] Screen transition and return processing in fragments
Call Java from JRuby
Changes from Java 8 to Java 11
Sum from Java_1 to 100
Eval Java source from Java
Run PostgreSQL on Java
Access API.AI from Java
From Java to Ruby !!
JAVA constructor call processing
Call a program written in Swift from Processing (Java)
Java random, various processing
Run Processing on Ant
Java to fly data from Android to ROS of Jetson Nano
Run R from a tomcat-powered Java process on Amazon Linux
Check communication from Android to node.js server with protocol buffers
Migration from Cobol to JAVA
Run batch with docker-compose with Java batch
[Java] Multi-thread processing --Exclusive control
Java starting from beginner, override
Creating ElasticSearch index from Java
New features from Java7 to Java8
Connect from Java to PostgreSQL
java hello world, compile, run
Java, instance starting from beginner
[Java] Stream API --Stream termination processing
[Java] Stream API --Stream intermediate processing
[Java] Timer processing implementation method
Run java applet on ubuntu
Java starting from beginner, inheritance
Measured parallel processing in Java
Understanding Java Concurrent Processing (Introduction)
Java life starting from scratch
[Java] [Android] Read ini file
Using Docker from Java Gradle
From Ineffective Java to Effective Java
JavaScript as seen from Java
Run Java VM with WebAssembly
Summary of java error processing
[Android / Java] Learned about DataBinding
Execute non-Java instructions from Java
Android: How to deal with "Could not determine java version from '10 .0.1'"
[Android, Java] Method to find the elapsed date from two dates
From fledgling Java (3 years) to Node.js (4 years). And the impression of returning to Java