我使用的是虚拟android设备,故对应的CLE中库文件版本为/x86,你可以根据自己开发环境找到对应的版本。调用的python版本为3.7,以下为主要步骤:

1、环境准备

在官网下载最新的CLE for Android 开发包,其中包含示例工程和API文档。

python调用android so文件 python调用安卓so库_tensorflow模型

解压开发包,拷贝如下文件

  1. 拷贝 starcore_android_rX.X.jar到工程的libs目录。(该jar文件在download的starcore_for_android.3.2.0中)
  2. 拷贝libstar_java.so、libstarcore.so、libpython3.7m.so和libstar_python37.so到libs/x86目录。(除了libpython3.7m.so在android.python.3.7.0下载文件中,其余都在download的starcore_for_android.3.2.0/libs/x86中)

2、编写Python代码

/----test.py----/
def add(x,y) :
 return x+y/----calljava.py----/
import imp #test load path
 def log(content):
 JavaClass.d(“formPython”,content)
 log(“Hello Android,form python”)/----py_code.py----/
import time
 def get_time():
 return time.time()

将py_code.py压缩为py_code.zip文件。将编写的Python源码放入Android 工程的assets目录,其中还要包含一些Python需要的环境及标准库,见下图:(这些库文件都在android.python.3.7.0下载文件/x86目录下)

python调用android so文件 python调用安卓so库_Android Studio_02


如果没有发现assets目录,则如下选择Android下添加:

python调用android so文件 python调用安卓so库_tensorflow模型_03

3、编写Android相关代码,初始化CLE并调用Python

首先需要修改build.gradle文件:

python调用android so文件 python调用安卓so库_python_04


添加jni库文件路径:

// jni配置
    sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
        }
    }

然后编写Android相关代码,初始化CLE并调用Python

import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.os.AsyncTask;
import android.app.Activity;
import android.util.Log;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.util.*;
import com.srplab.www.starcore.*;


public class MainActivity extends AppCompatActivity {

    public StarSrvGroupClass SrvGroup;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });
        final File appFile = getFilesDir();  /*-- /data/data/packageName/files --*/
        final String appLib = getApplicationInfo().nativeLibraryDir;

        loadPy(appFile,appLib);
//        AsyncTask.execute(new Runnable() {
//
//            @Override
//            public void run() {
//                loadPy(appFile,appLib);
//            }
//        });
    }

    void loadPy(File appFile,String appLib){
        //拷贝Python相关环境
        File pythonLibFile = new File(appFile, "python3.7.zip");
        if (!pythonLibFile.exists()) {
            copyFile(this, "python3.7.zip");
            copyFile(this, "_struct.cpython-37m.so");
            copyFile(this, "binascii.cpython-37m.so");
            copyFile(this, "time.cpython-37m.so");
            copyFile(this, "zlib.cpython-37m.so");
        }

        // 拷贝Python 代码
        copyFile(this, "calljava.py");
        copyFile(this, "test.py");

        try {
            // 加载Python解释器
            System.load(appLib + File.separator + "libpython3.7m.so");

            // 除了将代码直接拷贝,还支持将代码压缩为zip包,通过Install方法解压到指定路径
            InputStream dataSource = getAssets().open("py_code.zip");
            StarCoreFactoryPath.Install(dataSource, appFile.getPath(),true );
        } catch (Exception e) {
            e.printStackTrace();
        }

        /*----init starcore----*/
        StarCoreFactoryPath.StarCoreCoreLibraryPath = appLib;
        StarCoreFactoryPath.StarCoreShareLibraryPath = appLib;
        StarCoreFactoryPath.StarCoreOperationPath = appFile.getPath();

        StarCoreFactory starcore = StarCoreFactory.GetFactory();
        StarServiceClass Service = starcore._InitSimple("test", "123", 0, 0);
        SrvGroup = (StarSrvGroupClass) Service._Get("_ServiceGroup");
        Service._CheckPassword(false);
        /*----run python code----*/
        SrvGroup._InitRaw("python37", Service); // this place
        StarObjectClass python = Service._ImportRawContext("python", "", false, "");
        /*调用tensorflow*/
        //个人推荐使用这种写法,看起来比较直观,不容易带给自己误解
        python._Call("eval", "import sys");
//        python._Call("eval", "sys.path.append(r'" + path + "')");
        python._Call("eval", "import numpy as np");
        python._Call("eval", "import pred as pd");
        //这里在导入tensorflow模型后获得模块接口,可以使用model._Call("func")
        //相当于python._Call("eval", "pd.func()"),但是前一种方法没法保存返回结果
        StarObjectClass model = python._GetObject("pd");
        python._Call("eval", "import operate_data as processor");
//        processor = python._GetObject("processor");


        // 设置Python模块加载路径
        python._Call("import", "sys");
        StarObjectClass pythonSys = python._GetObject("sys");
        StarObjectClass pythonPath = (StarObjectClass) pythonSys._Get("path");
        pythonPath._Call("insert", 0, appFile.getPath()+ File.separator +"python3.7.zip");
        pythonPath._Call("insert", 0, appLib);
        pythonPath._Call("insert", 0, appFile.getPath());

        //调用Python代码
        Service._DoFile("python", appFile.getPath() + "/py_code.py", "");
        long time = python._Calllong("get_time");
        Log.d("", "form python time="+time);

        Service._DoFile("python", appFile.getPath() + "/test.py", "");
        int result = python._Callint("add", 5, 2);
        Log.d("", "result="+result);

        python._Set("JavaClass", Log.class);
        Service._DoFile("python", appFile.getPath() + "/calljava.py", "");
    }

    private void copyFile(Activity c, String Name) {
        File outfile = new File(c.getFilesDir(), Name);
        BufferedOutputStream outStream = null;
        BufferedInputStream inStream = null;

        try {
            outStream = new BufferedOutputStream(new FileOutputStream(outfile));
            inStream = new BufferedInputStream(c.getAssets().open(Name));

            byte[] buffer = new byte[1024 * 10];
            int readLen = 0;
            while ((readLen = inStream.read(buffer)) != -1) {
                outStream.write(buffer, 0, readLen);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (inStream != null) inStream.close();
                if (outStream != null) outStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

以上是我新建了一个basic activity工程,里面的MainActivity.java文件中初始化python模块并调用文件和函数代码。
代码中python._Set(“JavaClass”, Log.class)一句,指将一个java类设置给Python,变成Python类,第一个参数指定在Python中的类名,此处随意起了一个类名JavaClass,该类可直接在Python中使用,如上将Android的日志输出类设置给Python使用,完成了Java与Python的互相调用。具体tensorflow模型的使用还只是初尝,等我全部走完美了再来补充。