1. 程式人生 > >android 呼叫 python

android 呼叫 python

文章可以幫你解決android下呼叫python方法獲取返回值,往python函式中傳參等。。。

你可能會遇到的問題

1:注意so版本;版本都要一致,從開發包裡複製貼上;
2:注意so引入路徑;as和ec是有區別的;

有什麼問題大家可以一起討論,之前找了很多資料,只有這個最後成功了,但是開始也有很多問題,還有通過JNI的 , 但是引入python.h 和python libs有問題VC上可以,在AS這個開發工具上怎麼搞不知道,,現在這種移植也還行,簡單,比較方便;之前還看了SL4A那個 也太扯淡了 ; jython在jvm環境下編譯沒毛病,一個jar搞定,但是如果在android下編譯,那就不能用了,dvm和jvm確實不一樣的;;;還是第一次直觀的表現出來;還有一些其它的,太難懂,就不一一說了;

如下圖:

libs的和jniLibs裡面的so;
這裡寫圖片描述

assets中放.py的檔案和python的zip包;

我的add.py檔案的程式碼

import time

def get_time():
    return time.time();

print("sin sin sin sin sin")

def add_num(a,b):  // 相加
    return a+b

def get_array(a): // 外邊傳入一個數組
    return a[0]  

def get_Str():  // 返回字串
    return "sin niu bi"

裡面import time 這裡會爆紅,需要把 time.cpython-34m.so放到assets下面可以執行get_time()這個函式;

下面是程式碼;

public class MainActivity extends Activity {

    static {
        System.loadLibrary("native-lib");
    }

    public native String stringFromJNI();


    public StarSrvGroupClass SrvGroup;

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

        TextView tv1 = (TextView) findViewById(R.id.sample_text1);
        TextView tv2 = (TextView) findViewById(R.id.sample_text2);
        TextView tv3 = (TextView) findViewById(R.id.sample_text3);
        TextView tv4 = (TextView) findViewById(R.id.sample_text4);
        TextView tv5 = (TextView) findViewById(R.id.sample_text5);
//        tv.setText(stringFromJNI());
// // TODO: 2018/5/4 File destDir = new File("/data/data/" + getPackageName() + "/files"); if (!destDir.exists()) destDir.mkdirs(); java.io.File python_libFile = new java.io.File("/data/data/" + getPackageName() + "/files/python3.4.zip"); if (!python_libFile.exists()) { try { copyFile(this, "python3.4.zip", null); } catch (Exception e) { System.out.println("cccccccc/// " + e); } } try { copyFile(this, "add.py", ""); } catch (Exception e) { System.out.println("aaaaaaaaa/// " + e); } try { // copyFile(this, "_struct.cpython-34m.so", null); // copyFile(this, "binascii.cpython-34m.so", null); copyFile(this, "time.cpython-34m.so", null); copyFile(this, "zlib.cpython-34m.so", null); // 這裡zlib需要加上,不知道具體用法,不加會報zlib引入錯誤;估計是so裡面有使用; } catch (Exception e) { System.out.println("DDDDDD/// " + e); } try { //--load python34 core library first; System.load(this.getApplicationInfo().nativeLibraryDir + "/libpython3.4m.so"); Log.e("aaaaa", "aaaaaaaaaaaaa-->" + this.getApplicationInfo().nativeLibraryDir + "/libpython3.4m.so"); } catch (UnsatisfiedLinkError ex) { Log.e("aaaaa", "bbbbbbbbbbbbbbb"); System.out.println("bbbbbbbbbb/// " + ex.toString()); Log.e("ssssss", "qweqweqwe-->" + this.getApplicationInfo().nativeLibraryDir + "/libpython3.4m.so"); } /*----init starcore----*/ StarCoreFactoryPath.StarCoreCoreLibraryPath = this.getApplicationInfo().nativeLibraryDir; StarCoreFactoryPath.StarCoreShareLibraryPath = this.getApplicationInfo().nativeLibraryDir; StarCoreFactoryPath.StarCoreOperationPath = "/data/data/" + getPackageName() + "/files"; 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("python34", Service); StarObjectClass python = Service._ImportRawContext("python", "", false, ""); python._Call("import", "sys"); StarObjectClass pythonSys = python._GetObject("sys"); StarObjectClass pythonPath = (StarObjectClass) pythonSys._Get("path"); pythonPath._Call("insert", 0, "/data/data/" + getPackageName() + "/files/python3.4.zip"); pythonPath._Call("insert", 0, this.getApplicationInfo().nativeLibraryDir); pythonPath._Call("insert", 0, "/data/data/" + getPackageName() + "/files"); // String CorePath = "/data/data/" + getPackageName() + "/files"; Service._DoFile("python", CorePath + "/add.py", ""); int _Callint = python._Callint("add_num", 5, 8); Log.e("ssssss", "_Callint: " + _Callint); Object add_num1 = python._Call("add_num", 1, 6); int a = (int) add_num1; Log.e("aaa", a + ""); tv1.setText("python中計算5+8: " + _Callint + ""); tv2.setText("python中計算1+6: " + a + ""); short[] arrS = {456, 254, 693}; //get_array Object get_array = python._Call("get_array", arrS); String s = get_array.toString(); // short[] aaa = (short[]) get_array; Log.e("ccc", "aaa.len: " + s); Object get_str = python._Call("get_Str"); Log.e("dddd", "get_str: " + (String) get_str); tv3.setText("往python中傳遞一個數組 {456, 254, 693},python中獲取第一個值並返回: " + s + ""); tv4.setText("python返回一個字串: " + (String) get_str + ""); Object get_time = python._Call("get_time"); Log.e("tttt","get_time: "+get_time); } private void copyFile(Activity c, String Name, String desPath) throws IOException { File outfile = null; if (desPath != null) outfile = new File("/data/data/" + getPackageName() + "/files/" + desPath + Name); else outfile = new File("/data/data/" + getPackageName() + "/files/" + Name); //if (!outfile.exists()) { outfile.createNewFile(); FileOutputStream out = new FileOutputStream(outfile); byte[] buffer = new byte[1024]; InputStream in; int readLen = 0; if (desPath != null) in = c.getAssets().open(desPath + Name); else in = c.getAssets().open(Name); while ((readLen = in.read(buffer)) != -1) { out.write(buffer, 0, readLen); } out.flush(); in.close(); out.close(); //} } }

好了,大功告成,總之現在是可以呼叫了,還不知道在複雜的python程式碼下能不能經得起考驗 ,反正目前這樣看著是沒有問題的;有問題及時討論。。。
另外,剛開始網上找解決辦法看的這篇文章: https://blog.csdn.net/yingshukun/article/details/78571992
這裡面也有其他方式呼叫python,有興趣也可以看看;
此處謝謝大佬分享。