这个其实就是个人的一个小小的兴趣,用C/C++写一个小程序放在Android的系统中,然后用Java写一个Android的UI程序来调用这个C/C++的程序。这里总结了实现这个功能的一些步骤和遇到的问题。蛮有意思的。
这里参考了下面两篇博文,主要是关于搭建arm-linux-gcc交叉编译环境的,非常有帮助,感谢他们的分享。
http://blog.csdn.net/super005/article/details/6369577
http://mawenhao19930620.blog.163.com/blog/static/128575361201212211291763/
http://www.cnblogs.com/huaping-audio/archive/2009/08/27/1555089.html
这里主要分四步:
1)搭建一个交叉编译环境,这里用的是Ubuntu的虚拟机来编译出一个可以在Android系统上运行的二进制文件;
2) 写一个 hello.c 的测试用的C程序 ,并且把它编译成可执行文件;
3)把可执行文件上传到Android系统中,及一些注意事项。
4)写一个Java的UI程序来调用这个测试的C程序。
主要参考了上面两个链接中的文章,简单而非常有帮助。
这里需要交叉编译的主要原因是Android系统源于Linux但不同于Linux,Linux上的程序无法直接在Android上运行。需要重新编译才行。Android设备主要基于 ARM的,在PC上的程序基于的X86的结构,这也导致了Linux下的程序必须重新编译才能在Android下运行。
在两篇文章中都提到了使用一个编译工具
arm-none-linux-gnueabi
一个使用的是 2009 版本的,一个是2008版本的。
配置方式都是把目标压缩文件Copy到一Linux的系统上,然后解压缩,设置PATH,
使用arm-none-linux-gnueabi-gcc 命令编译程序。
这里保存一下两个工具的下载地址
arm-2010.09-50-arm-none-linux-gnueabi
arm-2008q3-41-arm-none-linux-gnueabi
在Linux配置 PATH的方法 (Ubuntu)
1) su nano ~/.bashrc
2) 在文件末尾添加如下的一行
export PATH=$PATH:/... .../... .../arm-2010.09-50/bin
3) 保存文件并退出
4) 运行命令 source ~/.bashrc
5) 当然可以用命令行验证一下是否成功 arm-none-linux-gnueabi-gcc --version。
写一个简单的HelloWorld.c 的程序(最爱)。
#include
int main()
{
int i=0;
printf("hi ym012 %d/n",i);
return;
}
这里注意使用 -static 选项,测试时我没有使用这个参数,结果编译出来的程序在Android系统中是没法运行的。
把编译好的HelloWorld程序使用 adb push 上传的一个Android系统中。这里测试时使用的是一个Android虚拟机,其中虚拟了一个 256M的sdcard。这里把程序先上传到sdcard有一个好处是基本不会失败。
上传程序后当然可以尝试着在Android Shell 中运行编译好的程序。
1) 使用 adb shell, 进入Android 的命令行。
2) cd /mnt/sdcard 进入HelloWorld的存储位置。
3) ./HelloWorld 执行程序,
但如果尝试在sdcard 中运行程序多半会遇到一个Permision Denied一个错误。
我们可以简单尝试使用 chmod 777 HelloWorld来修复它,但再次运行程序时多半还会失败。
网上找了找原因,给出的解释是Android不能修改 sdcard下 程序的权限,最简单的老老实实把它复制到Android系统下的某个文件夹下吧。
4) cp /mnt/sdcard/HelloWorld /data/ 复制文件到Android的data目录下
5) chmod 777 HelloWorld 修改权限
6) ls -l 当然可以在查询一下,但也不是必须的。
7) ./HelloWorld 运行程序
这时基本已经可以了。
如果交叉编译出来的程序不正确在这里是没法运行的,出现 error: magic 7F45 基本上就是交叉编译出的问题了。
程序实例:
MainActivity.java
package com.example.systeminformation;
import java.io.IOException;
import android.os.Bundle;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Intent;
import android.view.View;
import android.widget.Button;
public class MainActivity extends Activity
{
private Button btnRunHello;
private Intent intent;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnRunHello = (Button) findViewById(R.id.id_run_hello);
btnRunHello.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View arg0)
{
CMDExecute m_Executor = new CMDExecute();
String m_strResult = "";
String arg[] = {"/data/hello"};
try
{
m_strResult = m_Executor.run(arg, "/data");
}
catch (IOException e)
{
e.printStackTrace();
}
new AlertDialog.Builder(MainActivity.this)
.setTitle("Run Hello")
.setMessage(m_strResult)
.setPositiveButton("确定", null)
.show();
}
});
}
}
CMDExecute,java
package com.example.systeminformation;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
public class CMDExecute
{
public synchronized String run(String[] cmd, String workdirectory) throws IOException
{
String result = "";
try
{
ProcessBuilder builder = new ProcessBuilder(cmd);
if (workdirectory != null)
{
builder.directory(new File(workdirectory));
builder.redirectErrorStream(true);
Process process = builder.start();
InputStream in = process.getInputStream();
byte[] re = new byte[1024];
while (in.read(re) != -1)
{
System.out.println(new String (re));
result = result + new String(re);
}
in.close();
}
}
catch(Exception ex)
{
ex.printStackTrace();
}
return result;
}
}
运行结果: