最近做了一些关于Android Native 编程相关的东西,在这篇文章中我将介绍如何在Android application中调用Native executable。至于如何编写Native executable如何打包native到apk中,之前我都有文章介绍这里就不再重复了。

我写了一个Demo程序,演示如何在Android Application中调用Native executable。该示例中:

  • 可以调用系统自带的executable,例如“/system/bin/ls”;
  • 可以调用自己编写的Native executable,放置在apk的assets目录下;
  • 可以调用从远程服务器下载的Native executable;

接下来详细介绍代码的实现,在这里我们主要用到了android.os.Exec,但是android.os.Exec不被包含在android.jar中,因此只能通过java反射机制来实现。

以下代码实现了一个通用的exec函数:

private String exec(String arg0, String arg1, String arg2) {
		try {
			// android.os.Exec is not included in android.jar so we need to use reflection.
			Class execClass = Class.forName("android.os.Exec");
	        Method createSubprocess = execClass.getMethod("createSubprocess",
	        		String.class, String.class, String.class, int[].class);
	        Method waitFor = execClass.getMethod("waitFor", int.class);

	        // Executes the command.
	        // NOTE: createSubprocess() is asynchronous.
	        int[] pid = new int[1];
	        FileDescriptor fd = (FileDescriptor)createSubprocess.invoke(
	        		null, arg0, arg1, arg2, pid);

	        // Reads stdout.
	        // NOTE: You can write to stdin of the command using new FileOutputStream(fd).
	        FileInputStream in = new FileInputStream(fd);
	        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
	        String output = "";
	        try {
		        String line;
				while ((line = reader.readLine()) != null) {
					output += line + "\n";
				}
			} catch (IOException e) {
				// It seems IOException is thrown when it reaches EOF.
			}

			// Waits for the command to finish.
			waitFor.invoke(null, pid[0]);

			return output;
		} catch (ClassNotFoundException e) {
			throw new RuntimeException(e.getMessage());
		} catch (SecurityException e) {
			throw new RuntimeException(e.getMessage());
		} catch (NoSuchMethodException e) {
			throw new RuntimeException(e.getMessage());
		} catch (IllegalArgumentException e) {
			throw new RuntimeException(e.getMessage());
		} catch (IllegalAccessException e) {
			throw new RuntimeException(e.getMessage());
		} catch (InvocationTargetException e) {
			throw new RuntimeException(e.getMessage());
		}
    }

以下代码实现如何执行assets中的Native executable程序:

private int getassetsfile(String fileName, String tagFile) {
    	int retVal = 0;
    	try {

    		File dir = new File(tagFile);
			if (dir.exists()) {
				dir.delete();
			}

    		InputStream in = this.getAssets().open(fileName);
    		if(in.available() == 0) {
    			return retVal;
    		}

    		FileOutputStream out = new FileOutputStream(tagFile);
			int read;
			byte[] buffer = new byte[4096];
			while ((read = in.read(buffer)) > 0) {
				out.write(buffer, 0, read);
			}
			out.close();
			in.close();

			retVal = 1;
			return retVal;
		} catch (IOException e) {
			throw new RuntimeException(e.getMessage());
		}
    }

以下代码实现如何执行远程服务器上的Native executable程序:

private void download(String urlStr, String localPath) {
    	try {
			URL url = new URL(urlStr);
			HttpURLConnection urlconn = (HttpURLConnection)url.openConnection();
			urlconn.setRequestMethod("GET");
			urlconn.setInstanceFollowRedirects(true);
			urlconn.connect();
			InputStream in = urlconn.getInputStream();
			FileOutputStream out = new FileOutputStream(localPath);
			int read;
			byte[] buffer = new byte[4096];
			while ((read = in.read(buffer)) > 0) {
				out.write(buffer, 0, read);
			}
			out.close();
			in.close();
			urlconn.disconnect();
		} catch (MalformedURLException e) {
			throw new RuntimeException(e.getMessage());
		} catch (IOException e) {
			throw new RuntimeException(e.getMessage());
		}
    }

 总结下:

通常有三种方法把Native executable放置到手机上:1.assets;2.via network;3.via pc use adb。在本例子中前两种方法都有实现,至于第三种我相信地球人都知道。

下载演示程序:DemoNativeExe_apk (212)

下载源代码:DemoNativeExeSrc (305)

    androidnative

转载请注明: 转载自iT人 – theiter

本文链接地址: 在Android上运行native可执行程序

相关文章