前言
文章可以帮你解决android下调用python方法获取返回值,往python函数中传参等。开发环境基于Android studio.
详细介绍
一.环境准备
在官网下载最新的CLE for Android 开发包,其中包含示例工程和API文档。解压开发包,拷贝如下文件
http://www.srplab.com/cn/files/products.html
你可能会遇到的问题
1:注意so版本;版本都要一致,从开发包里复制粘贴;
2:注意so引入路径;as和ec是有区别的;
- 拷贝 starcore_android_rX.X.jar的arm64-v8a目录内容到工程的libs目录
- 拷贝starcore_android_rX.X.jar的到starcore_android_r3.7.dex、starcore_android_r3.7.jar到libs目录
如下图:
libs的和assets里面的so;
二、编写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里面arm64-v8a\lib-dynload中找到对应的so库),见下图
三、编写Android相关代码,初始化CLE并调用Python
package com.cootf.mytest;
import android.app.Activity;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.RemoteException;
import android.telephony.TelephonyManager;
import android.util.Log;
import com.srplab.www.starcore.StarCoreFactory;
import com.srplab.www.starcore.StarCoreFactoryPath;
import com.srplab.www.starcore.StarObjectClass;
import com.srplab.www.starcore.StarServiceClass;
import com.srplab.www.starcore.StarSrvGroupClass;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.concurrent.TimeUnit;
import rx.Observable;
import rx.Observer;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
public class MainActivity extends Activity {
private static final String TAG = MainActivity.class.getSimpleName();
private Subscription mSubscription;
ActivityManager mAm;
public StarSrvGroupClass SrvGroup;
private StarServiceClass Service;
private StarCoreFactory starcore;
private StarObjectClass python;
private File appFile ;
private String appLib ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG,"onCreate");
setContentView(R.layout.activity_main);
mAm = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
Iterator<ActivityManager.RunningTaskInfo> iter = mAm.getRunningTasks(100).iterator();
appFile = getApplicationContext().getFilesDir(); /*-- /data/data/packageName/files --*/
appLib = getApplicationInfo().nativeLibraryDir;
loadPy();
}
void loadPy(){
loadPyEnviroment();
initCle();
runPy();
}
private void loadPyEnviroment() {
//拷贝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-34m.so");
copyFile(this, "zlib.cpython-37m.so");
}
// 拷贝Python 代码
copyFile(this, "calljava.py");
//copyFileFromSdcard(this, "test.py"); //验证读取sdcard里面的文件也可以
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();
}
}
private void initCle() {
/*----init starcore----*/
StarCoreFactoryPath.StarCoreCoreLibraryPath = appLib;
StarCoreFactoryPath.StarCoreShareLibraryPath = appLib;
StarCoreFactoryPath.StarCoreOperationPath = appFile.getPath();
starcore = StarCoreFactory.GetFactory();
starcore._SRPLock();
Log.d(TAG,"zjy startcore:"+starcore);
SrvGroup = starcore._GetSrvGroup(0);
Log.d(TAG,"zjy SrvGroup:"+SrvGroup);
Service = SrvGroup._GetService("test","123");
Log.d(TAG,"zjy Service:"+Service);
if( Service == null ){ // the service has not been initialized
Log.d(TAG,"zjy Service is null");
Service = starcore._InitSimple("test", "123", 0, 0);
}else{
Log.d(TAG,"zjy SrvGroup:"+SrvGroup);
Service._CheckPassword(false);
}
Service._CheckPassword(false);
/*----run python code----*/
SrvGroup._InitRaw("python37", Service); // this place
python = Service._ImportRawContext("python", "", false, "");
StarObjectClass model = python._GetObject("pd");
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());
starcore._SRPUnLock();
}
private void runPy() {
//调用Python代码
Service._DoFile("python", appFile.getPath() + "/py_code.py", "");
long time = python._Calllong("get_time");
Log.d(TAG, "form python time="+time);
Service._DoFile("python", appFile.getPath() + "/test.py", "");
int result = python._Callint("add", 5, 2);
Log.d(TAG, "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();
}
}
}
private void copyFileFromSdcard(Activity c, String Name) {
File outfile = new File(c.getFilesDir(), Name);
BufferedOutputStream outStream = null;
BufferedInputStream inStream = null;
InputStream redis = null;
try {
String sdpath = Environment.getExternalStorageDirectory().getAbsolutePath();
String filePath = sdpath +File.separator + Name;
redis = new FileInputStream(new File(filePath));
outStream = new BufferedOutputStream(new FileOutputStream(outfile));
inStream = new BufferedInputStream(redis);
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
protected void onStart() {
super.onStart();
Log.d(TAG,"onStart");
}
@Override
protected void onResume() {
super.onResume();
Log.d(TAG,"onResume");
}
@Override
protected void onPause() {
super.onPause();
Log.d(TAG,"onPause");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d(TAG,"onDestroy X");
starcore._ModuleClear();
// starcore._ModuleExit();
Log.d(TAG,"onDestroy E");
}
}
app的 build.gradle配置:
apply plugin: 'com.android.application'
android {
compileSdkVersion 25
defaultConfig {
applicationId "com.cootf.mytest"
minSdkVersion 14
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
// jni配置
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}