android-----JNI-----输入输出

本文详细介绍了如何使用Android.mk文件构建C程序为可执行文件,并将其与Android应用集成,实现线程间读写操作。通过布局、Java代码和Android部分的整合,展示了如何在Android应用中调用并控制外部可执行文件,提供了完整的测试代码和步骤说明。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

网上很多的JNI文章,几乎都是讲的编译成 .SO 几动态库文件,对于编译成可执行文件的很少,然而对编译成可执行文件几乎就是官方文档中的例子,这几天为了项目,自己做了小实验,特记录一下:

首先看一下目录结构:



首先看Android.mk 的内容

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE    := io
LOCAL_SRC_FILES := io.c
include $(BUILD_EXECUTABLE)


首先申明,由于是自己的测试,所以代码写得很丑哦!!!!

io.c 的代码:(为了工程的需要我这里测试的在线程中读写直接在主函数中也可)

  <c程序编译后一定要将libs里面的名为io 的可执行文件拷贝到assets目录里面>

/*
 * io.c
 *
 *  Created on: 2014年1月22日
 *      Author: Jason
 */
#include <jni.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

void *start_routine (void *arg)
{
	while (1)
	{
		char buf[128] = { 0 };
		printf("please enter input .... \n");
		fflush(stdout);
		fgets(buf,128,stdin);
		printf("copy :  %s\n", buf);
		fflush(stdout);
		if(0 == strcmp(buf,"BREAK"))
					break;
		memset(buf,0,128);
	}
}

int main()
{
	pthread_t thread;
	if( 0 > pthread_create(&thread, NULL,start_routine, NULL))
	 {
		printf("pthread_create failed \n");
	 }
	pthread_join(thread,NULL);

	return 0;
}

---------------------------------------------------------------------------------------------------------------------------------------------------------

android部分

---------------------------------------------------------------------------------------------------------------------------------------------------------

1、布局

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <TextView
        android:id="@+id/textView"
        android:background="#bfbfbfbf"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@+id/editText1"
        android:layout_alignParentLeft="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:textColor="#003399"
        android:textSize="22sp"
        android:text="@string/hello_world" />

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@+id/button2"
        android:layout_alignBottom="@+id/button2"
        android:layout_alignLeft="@+id/textView"
        android:layout_marginLeft="37dp"
        android:text="读" />

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignRight="@+id/textView"
        android:layout_marginBottom="67dp"
        android:layout_marginRight="24dp"
        android:text="写" />

    <EditText
        android:id="@+id/editText1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@+id/button1"
        android:layout_alignLeft="@+id/textView"
        android:layout_alignRight="@+id/textView"
        android:layout_marginBottom="96dp"
        android:ems="10" />

</RelativeLayout>

2、JAVA部分

package com.example.jniio;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;

import android.os.Bundle;
import android.app.Activity;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends Activity 
{

	private static final String TAG = "CALLJNI";
	private TextView textView = null;
	private Button readButton = null;
	private Button writeButton = null;
	private EditText editText = null;

	private Process process = null;
	private PackageInfo mPInfo = null;
	private String text = "";

	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		init(); // ----- 实例化组件

		copyApplication("io"); //加载可执行文件

		//开线程,不阻碍ui线程
		new Thread(new Runnable()
		{
			@Override
			public void run()
			{
				try
				{
					//调用程序
					Log.i(TAG, "process action ....  ");
					process = new ProcessBuilder().directory(new File(mPInfo.applicationInfo.dataDir)).redirectErrorStream(true).command("./io").start();
					Log.i(TAG, "process actioned ");
				}
				catch (IOException e1)
				{
					e1.printStackTrace();
					Log.e(TAG, "process wrong !!! ");
				}

			}
		}).start();
	}

	/**
	 * 初始化 ---- 实例化
	 */
	private void init()
	{
		this.textView = (TextView) findViewById(R.id.textView);
		this.readButton = (Button) findViewById(R.id.button1);
		this.writeButton = (Button) findViewById(R.id.button2);
		this.editText = (EditText) findViewById(R.id.editText1);
		try
		{
			mPInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
		}
		catch (NameNotFoundException e2)
		{
			Log.e(TAG, "mPInfo  wrong !!! ");
			e2.printStackTrace();
		}
		
		textView.setText(text);
		
		readButton.setOnClickListener(new OnClickListener()
		{
			@Override
			public void onClick(View v)
			{
				text += "<<<: "+read()+"\n";
				Log.i(TAG, "<<< 读 : "+text);
				textView.setText(text);
			}
		});
		
		
		writeButton.setOnClickListener(new OnClickListener()
		{
			@Override
			public void onClick(View v)
			{
				String inputString = editText.getText().toString();
				Log.i(TAG, "<<< 写 : "+inputString);
				write(inputString+"\n");
				text += ">>>: "+inputString +"\n";
				textView.setText(text);
				editText.setText("");
			}
		});

	}

	/**
	 * 写
	 * 
	 * @param string
	 */
	public void write(String string)
	{
		Log.i(TAG, ">>>:write ....   "+string);
		if (process != null)
		{
			try
			{
				OutputStream out = process.getOutputStream();
				BufferedWriter bWriter = new BufferedWriter(new OutputStreamWriter(out));
				bWriter.write(string);
				bWriter.flush();
				Log.i(TAG, ">>>:write  OK!   ");
			}
			catch (Exception e)
			{
				// TODO: handle exception
			}
		}
	}

	/**
	 * 读
	 */
	public String read()
	{
		String outpString = null;
		try
		{
			InputStream in = process.getInputStream();
			BufferedReader bReader = new BufferedReader(new InputStreamReader(in));
			outpString = bReader.readLine();
			Log.i(TAG, "<<<:read() ....   "+outpString);
		}
		catch (Exception e)
		{
			// TODO: handle exception
		}

		return outpString;
	}

	/**
	 * android 不会加载除 .so的文件,所以对于可执行文件就得自己手动加载 我把可执行文件拷贝到 assets目录下,在程序运行时,在加载到运行的空间。
	 * 
	 * @param applicationName 可执行程序名
	 */
	public void copyApplication(String applicationName)
	{
		try
		{
			PackageInfo mPInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
			try
			{
				File of = new File(mPInfo.applicationInfo.dataDir + "/" + applicationName);
				InputStream in = getAssets().open(applicationName);
				OutputStream out = new FileOutputStream(of);

				byte[] buf = new byte[1024];
				int len;
				while ((len = in.read(buf)) > 0)
				{
					out.write(buf, 0, len);
				}
				in.close();
				out.close();
				Log.v(TAG, "copied " + applicationName);
			}
			catch (Exception e)
			{
				Log.e(TAG, "Error: Could not find " + applicationName, e);
				throw new Exception("Cannot find " + applicationName + " in assets.");
			}

			Log.v(TAG, "setting executable flag");
			Process process = new ProcessBuilder().directory(new File(mPInfo.applicationInfo.dataDir)).redirectErrorStream(true).command("chmod", "777", "./" + applicationName).start();		
			process.waitFor();
			int rvalue = process.exitValue();
			Log.v(TAG, "chmod returned : " + rvalue);
			if (rvalue != 0)
			{
				Log.v(TAG, "cannot set executable flag");
				throw new Exception("Cannot set executable flag.");
			}

		}
		catch (Exception e)
		{
			Log.e(TAG, "could not set up " + applicationName, e);
		}
	}

	@Override
	protected void onDestroy()
	{
		write("BREAK\n");
		super.onDestroy();
	}
	
	

}























评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值