精华内容
下载资源
问答
  • Android 平台的Python——基础篇(一)

    万次阅读 多人点赞 2017-11-18 22:26:08
    要想在Android平台运行起Python,也有方案实现,其实质就是在Android系统上搭建Python环境。对此Google已经提供了SL4A(Scripting Layer for Android )方案,支持多种脚本语言,除此之外,还可以使用一个

    Android 平台的Python——基础篇(一)
    Android 平台的Python——JNI方案(二)
    Android 平台的Python——CLE方案实现(三)
    Android 平台的Python——第三方库移植
    Android 平台的Python——编译Python解释器
    新篇——Android与Python混合编程

    前言
    (本文以Python3为例,Python3是未来,大家都懂的)
    Python作为一个功能强大又语法简洁的语言,其应用已无需多言。要想在Android平台运行起Python,也有方案实现,其实质就是在Android系统上搭建Python环境。对此Google已经提供了SL4A(Scripting Layer for Android )方案,支持多种脚本语言,除此之外,还可以使用一个叫QPython的app,可以直接在Android上编写以及运行Python代码。但其实意义不大,写好的Python代码并不是以一个独立的app进程运行的,只不过是在QPython这个应用中运行而已。这两者都不符合我现在要讨论的东西,如题,笔者想要讨论的是如何在Android平台使用Java与Python代码相互调用,换言之,就是如何在Android工程中嵌入一个Python解释器。

    首先谈一点,为什么要在Android平台使用Python?Python拥有众多强大的第三方库和框架,在机器学习、大数据处理等诸多方面都有不俗的应用。另外,就语法而言,Python比Java更加简洁,同时又功能强大,既可面向过程亦可面向对象,而不像Java一样,是一种纯粹的面向对象语言,哪怕打印一句话也需要先创建类。Python作为一种脚本语言,可以边解释边执行,而不需编译,另外Python中存在的元类,可以使我们动态的创建类,如此可以在不需要重新编译安装apk的情况下,动态的由远程服务端为Android项目添加功能。我们还可以将Python已有的一些东西移植到Android平台,例如tornado、django等,总之玩法多多。

    在Android平台,官方并不支持直接使用Python开发app,基于虚拟机的Java(或kotlin)才是更好的选择,其他语言是无法自如的使用官方Framework提供的api的,尤其是在程序界面的表现上,典型的反例就是kivy。什么是kivy,可自行了解,但要解决Android平台上Java与Python的交互,kivy确实是一个方向,而且是一个醍醐灌顶的方向。kivy实际上已经解决我们需要实现的目的,模仿Android平台上的kivy实现机制即可。但是,kivy使用了大量的Cython技术,而非CPython API接口,需要学习Cython语法,并且在其他一些方面存在一些限制。kivy给我们提供的思路就是借助Java的jni机制,实现Python与Java的交互。即在一个安卓apk工程中包含一个cython.so解释器,通过jni机制调用解释器去解释执行Python代码,通过Java调C,C调Python实现交互。有一点需要说明,Python作为一门胶水语言,Python与C的交互是非常方便的,因此才能实现这一系列调用。

    关于该种方案,已有国外网友实践,原理如下

    这里写图片描述

    链接地址

    除此之外,本博客将通过另外两种方案实现。其中第一种类似上述方案,但集成CPython解释器,非Cython,因此需要掌握如何实现Python与C的交互。

    Python与C交互基础

    C调用Python

    • 简单使用
      流程:

      • 初始化Python解析器
      • 执行Python代码,字符串,对象或模块。
      • 关闭Python解析器。

      创建一个.c源文件,代码如下,创建一个pytest.py文件,实现一个printTime函数

    	#include<Python.h>
    	int main()
    	{
    	    Py_Initialize();//初始化Python解析器
    	    if (!Py_IsInitialized())
    	    {
    		    printf("Initialize failed");
    		      return -1;
    	    }
    	    PyRun_SimpleString("print('hello C !')");
    	    PyRun_SimpleString("import pytest");
    	    PyRun_SimpleString("pytest.printTime()");
    	    Py_Finalize();/关闭Python解析器
    	    return 0;
    	}		
    

    注意:除了用PyRun_SimpleString函数直接运行代码,还可以使用PyRun_SimpleFile函数运行一个Python脚本
    原型:PyRun_SimpleFile(FILE *fp, const char *filename) ,由于版本差异,使用该方式可能会造成崩溃,推荐另一种替代方式
    PyRun_SimpleString(“execfile(“test.py”)”)

    • 调用Python函数
      pytest.py

      import time
      
      def printTime():
          print('invoke printTime:'+str(time.time()))
          return (1,)#元组只有一个元素时,需在末尾加逗号
      

      C 代码

      int main()
      {
      	PyObject * module_name,*module,*func,*dic;
      	char * fun_name = "printTime";//需调用的Python函数名
      	PyObject *resultValue;
      
      	Py_Initialize();
      	if (!Py_IsInitialized())
      	{
      		printf("Initialize failed");
      		return -1;
      	}
      
      	//导入Python 模块并检验
      	module_name = Py_BuildValue("s", "pytest");
      	module = PyImport_Import(module_name);
      
      
      	if (!module)
      	{
      		printf("import test failed!");
      		return -1;
      	}
      	
          //获取模块中的函数列表,是一个函数名和函数地址对应的字典结构
          dic = PyModule_GetDict(module);
      	if (!dic)
      	{
      		printf("failed !\n");
      		return -1;
      	}
      
      	func = PyDict_GetItemString(dic, fun_name);
      	if (!PyCallable_Check(func))
      	{
      		printf("not find %s\n", fun_name);
      		return -1;
      	}
      
      	int r;
          //获取Python函数返回值,是一个元组对象
      	resultValue = PyObject_CallObject(func, NULL);
      	PyArg_ParseTuple(resultValue, "i", &r);
      	printf("result :%d\n", r);
      
      	Py_DECREF(module);
          Py_DECREF(dic);
      	Py_Finalize();
      	return 0;
      }
      

    基础API

    C API 调用 Python 对应
    PyImport_ImportModel import module
    PyImport_ReloadModule reload(module)
    PyImport_GetModuleDict module._dict_
    PyDict_GetItemString dict[key]
    PyDict_SetItemString dict[key] = value
    PyDict_New dict = {}
    PyObject_GetAttrString getattr(obj, attr)
    PyObject_SetAttrString setattr(obj, attr, val)
    PyObject_CallObject funcobj(*argstuple)
    PyEval_CallObject funcobj(*argstuple)
    PyRun_String eval(exprstr) , exec(stmtstr)
    PyRun_File exec(open(filename().read())
    • Py_BuildValue()函数
      作用:将C/C++类型类型的数据转变成PyObject*对象。
      原型:PyAPI_FUNC(PyObject*) Py_BuildValue(const char *format, ...);

      参数解释:
      format及转换格式,类似与C语言中%d,%f,后面的不定参数对应前面的格式,具体格式如下:

      “s”(string) [char *] :将C字符串转换成Python对象,如果C字符串为空,返回NONE。

      “s#”(string) [char *, int] :将C字符串和它的长度转换成Python对象,如果C字符串为空指针,长度忽略,返回NONE。

      “z”(string or None) [char *] :作用同"s"。

      “z#” (stringor None) [char *, int] :作用同"s#"。

      “i”(integer) [int] :将一个C类型的int转换成Python int对象。

      “b”(integer) [char] :作用同"i"。

      “h”(integer) [short int] :作用同"i"。

      “l”(integer) [long int] :将C类型的long转换成Pyhon中的int对象。

      “c”(string of length 1) [char] :将C类型的char转换成长度为1的Python字符串对象。

      “d”(float) [double] :将C类型的double转换成python中的浮点型对象。

      “f”(float) [float] :作用同"d"。

      “O&”(object) [converter, anything] :将任何数据类型通过转换函数转换成Python对象,这些数据作为转换函数的参数被调用并且返回一个新的Python对象,如果发生错误返回NULL。

      “(items)”(tuple) [matching-items] :将一系列的C值转换成Python元组。

      “[items]”(list) [matching-items] :将一系列的C值转换成Python列表。

      “{items}”(dictionary) [matching-items] :将一系类的C值转换成Python的字典,每一对连续的C值将转换成一个键值对。

      例:
      后面为PyObject的返回值

            Py_BuildValue("")None
      
            Py_BuildValue("i",123) 123
      
            Py_BuildValue("iii",123, 456, 789) (123, 456, 789)
      
            Py_BuildValue("s","hello") 'hello'
      
            Py_BuildValue("ss","hello", "world") ('hello', 'world')
      
            Py_BuildValue("s#","hello", 4) 'hell'
      
            Py_BuildValue("()")()
      
            Py_BuildValue("(i)",123) (123,)     
      
            Py_BuildValue("(ii)",123, 456) (123, 456)
      
            Py_BuildValue("(i,i)",123, 456) (123, 456)
      
            Py_BuildValue("[i,i]",123, 456) [123, 456]      Py_BuildValue("{s:i,s:i}", "abc",123, "def", 456) {'abc': 123, 'def': 456}
      
            Py_BuildValue("((ii)(ii))(ii)", 1, 2, 3, 4, 5, 6) (((1, 2), (3, 4)), (5, 6))
      
    • PyArg_ParseTuple函数
      作用:此函数其实相当于sscanf(str,format,…),是Py_BuildValue的逆过程,这个函数将PyObject参数转换成C/C++数据类型,传递的是指针,但这个函数与Py_BuildValue有点不同,这个函数只能解析Tuple元组,而Py_BuildValue函数可以生成元组,列表,字典等。
      原型:PyAPI_FUNC(int) PyArg_ParseTuple(PyObject *args, const char *format,...)

        Args:一般为Python程序返回的元组。
         
        Foramt:与Py_BulidValue类型,就不在累述咯。
         
        元组操作函数:
        因为程序之间传递的参数,大多数为Tuple类型,所以有专门的函数来操作元组:
         
        PyAPI_FUNC(PyObject *)PyTuple_New(Py_ssize_t size);
        解释:新建一个参数列表(调试了下,发现其实是用链表实现的),size列表为长度的宽度
         
        PyAPI_FUNC(Py_ssize_t)PyTuple_Size(PyObject *);
        解释:获取该列表的大小
         
        PyAPI_FUNC(PyObject *)PyTuple_GetItem(PyObject *, Py_ssize_t);
        解释:获取该列表某位置的值
         
        PyAPI_FUNC(int) PyTuple_SetItem(PyObject *,Py_ssize_t, PyObject *);
        解释:设置该列表此位置的值。如PyTuple_SetItem(pyParams,1,Py_BuildValue("i",2));设置第2个位置的值为2的整数。	
      

      备注:对应的列表和字典也有对应的操作

    更多的接口调用以及数据类型转化,参照Python文档
    这里写图片描述

    Python 调用C

    Python调用C有两种方式

    • 使用ctypes模块,Python文档有详细示例
      这里写图片描述

    • 使用C为Python编写拓展模块
      Python之所以如此强大,正是由于可以使用C\C++为其编写拓展模块,手动编写拓展模块的方式稍微有些繁琐,可借用SWIG自动实现,简洁快速。更多详细的SWIG用法,见其官方文档
      官网下载 windows包并解压

      使用vs创建空项目,并配置vs。右键当前项目,选择属性
      这里写图片描述
      现在使用C为Python创建一个叫user的拓展模块,该模块包含一个showHello函数:
      分别创建三个文件
      user.i
      user.c
      user_wrap.c

    在user.i中添加如下代码

    	%module user
    	
    	%inline %{
    	extern void showHello();
    	%}
    

    user.c中添加

    	#include <stdio.h>
    	void showHello()
    	{
    		printf("hello Python!\n");
    	}
    

    右键user.i 文件并选择属性
    这里写图片描述
    点击应用后如下图,完成配置
    这里写图片描述
    右键当前项目,选择属性,完成如下配置,确定
    这里写图片描述
    最后生成即可(选择工具栏 生成 --> 批生成)

    创建测试代码调用C验证

    import user
    user.show()
    

    在Linux下则无需如此麻烦的配置,可直接使用命令

    On Unix the compilation of examples is done using the file Example/Makefile. This makefile performs a manual module compilation which is platform specific. Typically, the steps look like this (Linux):
    
    
    % swig -python interface.i
    % gcc -fpic -c interface_wrap.c -I/usr/local/include/python1.5
    % gcc -shared interface_wrap.o $(OBJS) -o interfacemodule.so 
    % python
    Python 1.5.2 (#3, Oct  9 1999, 22:09:34)  [GCC 2.95.1 19990816 (release)] on linux2
    Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam
    >>> import interface
    >>> interface.blah(...)
    

    此处.i文件为SWIG的接口文件,其中%module后面定义模块名,用%inline定义方法列表

    %inline %{
    包含导出的函数
    %}
    

    有了Python与C的交互基础,则还需要Android中的NDK开发基础,关于Android平台的jni调用,本文不在此处详解,可看看我的JNI方面博客,而此处我们需要使用Crystax NDK开发工具链,非官方NDK工具链,需自行下载。下一篇正式涉及Python for Android。

    关注个人公众号:编程之路从0到1

    编程之路从0到1

    展开全文
  • Android Studio导入Android平台源码

    千次阅读 2021-01-06 10:46:49
    作为Android平台开发者,需要阅读和编写Android平台源码,一个好的工具可以事半功倍。 本文介绍如何通过Android Studio 导入Android平台源码

    作为Android平台开发者,需要阅读和编写Android平台源码,一个好的工具可以事半功倍。

    本文介绍如何通过Android Studio 导入Android平台源码。

    平台和软件信息

    • Android Studio 4.1.1
    • Ubuntu 20.04
    • Android 10.0 源码
    • Android根目录:/home/tanfh/data/code/android/

    一键生成Android.ipr文件

    通过Android Studio打开工程需要生成一个Android.ipr文件,笔者封装了一个shell脚本命令,请按照如下方法下载脚本并执行即可:

    1. 下载脚本点击下载android_studio_ipr,解压缩,比如存放于:/home/tanfh/Downloads/
    2. 进入Android源码根目录,执行:
    chmod a+x /home/tanfh/Downloads/generate_android_studio_ipr/studio_impl.sh
    /home/tanfh/Downloads/generate_android_studio_ipr/studio_impl.sh
    

    如上命令执行完成之后,会生成:

    • android.iml 模块配置文件,可以配置模块的资源**目录和过滤目录等。详细可以参考A module file (the .iml file)
    • android.ipr 工程相关的设置。详细可以参考 ipr
    • android.iws 工作区的设置。

    关于这几个文件的官方介绍:

    • *.iml and *.ipr files were project wide and could go into source control
    • *.iws manages workspace settings specific to a user so shouldn’t go into source control
    1. 打开Android Studio->File->Open 打开生成的android.ipr文件。
    2. 导入源码就完成了,等待AS Indexing完成即可。

    技巧

    如下内容详细分析脚本的原理以及高级用法,如果没有特殊需求,本文后续内容可以不用在关注。

    过滤文件

    google开发了一套工具来方便生成, AS可以识别的android.ipr文件。源码位于:

    development/tools/idegen

    如果将所有的文件都载入Android Studio,会导致indexing非常慢,读者可以根据自己的模块需求过滤掉不需要的文件和目录。

    idegen可以通过excluded-paths 文件来过滤不参与indexing的文件和目录。

    详细介绍可以查看excluded-paths文件内部开头介绍,全部是正则表达式,一个表达式一行。摘取片段介绍如下:

    ^(?!frameworks|packages|libcore|vendor|out|wingos|external)
    ^frameworks/(?!base|native|support|ex|opt|webview|av|minikin)
    
    • 第一句含义:不过滤frameworks、packages、libcore、vendor、out目录
    • 第二句含义:不过滤frameworks/base等

    读者有任何需要过滤的可以按照如上方法进行编写即可,由于笔者工作集中在framework和apps,所以默认有如下的配置文件,读者可以根据自己的需要进行定制。

    ^(.*/tests/.*)$
    #exclude all jar
    ^(?!.*android-support-.*_intermediates/.*).*\.jar$
    ^(?!.*androidx.*_intermediates/.*).*\.jar$
    
    ^(?!frameworks|packages|libcore|vendor|out|wingos|external)
    #ssl : apache-http|conscrypt|bouncycastle
    ^external/(?!apache-http|conscrypt|bouncycastle|jsr330|dagger2)
    
    
    ^frameworks/(?!base|native|support|ex|opt|webview|av|minikin)
    ^frameworks/base/(?!core|libs|services|packages|policy|media|telephony|graphics|cmds|telecomm|keystore|tools)
    ^frameworks/base/packages/(?!SettingsProvider|SystemUI|Keyguard|)
    
    
    # package
    
    ^packages/(?!screensavers|WingUI|apps|providers|services)
    ^packages/apps/(?!Settings|SamSungCamera2|Launcher3)
    #####for android 5.1
    #^packages/apps/Email/(?!.*)
    ^packages/experimental
    ^packages/inputmethods
    ^packages/wallpapers
    
    
    ^out/(?!target|soong)
    ^out/target/(?!common|product)
    ^out/soong/(?!.intermediates)
    ^out/soong/.intermediates/(?!frameworks)
    ^out/soong/.intermediates/frameworks/(?!base)
    ^out/soong/.intermediates/frameworks/base/(?!core|framework|packages)
    ^out/soong/.intermediates/frameworks/base/framework/(?!android_common)
    # android o add gen
    ^out/target/common/(?!obj|R|gen)
    ^out/target/common/obj/(?!JAVA_LIBRARIES|APPS)
    ^out/target/common/obj/APPS/(?!Email_intermediates|framework-res_intermediates|SystemUI_intermediates|wos-framework-res_intermediates)
    ^out/target/common/obj/JAVA_LIBRARIES/(?!framework_intermediates.*|framework2_intermediates|framework-base_intermediates|com.android.emailcommon_intermediates|mediatek-common_intermediates|uiautomator_intermediates|telephony-ext_intermediates|android-support.*_intermediates.*)
    
    
    
    #y360
    ^mediatek/packages
    #g628
    ^mediatek/operator
    ######################mediateck###########################
    
    
    ######################mediateck###########################
    ^vendor/(?!mediatek|qcom|wingos)
    ^vendor/widevine
    #^vendor/lenovo
    
    ^vendor/mediatek/proprietary/(?!frameworks|packages)
    #^vendor/mediatek/proprietary/packages/app(?!frameworks|packages)
    ^vendor/mediatek/proprietary/packages/(?!apps)
    ^vendor/mediatek/proprietary/packages/apps/(?!BackupRestore|Mms|Calendar|SamSungCamera)
    
    ^vendor/qcom/(?!proprietary)
    ^vendor/qcom/proprietary/(?!qrdplus)
    ^vendor/qcom/proprietary/qrdplus/(?!ChinaMobile|Extension|DataMonitor)
    ^vendor/qcom/proprietary/qrdplus/ChinaMobile/apps/(?!Backup|BackupReceiver)
    

    通过AS exclude文件和标记文件为source root

    除了根据脚本生成相关文件之外,还可以可以通过Android Studio直接取消过滤和标记过滤。

    比如想取消 packages/apps/SecureElement 的过滤

    1. 选中SecureElement
    2. 右键-》mark directory as-》cancel exclusion
    3. 点击src目录-》右键-》mark directory as-》source root
    4. 经过如上步骤,SecureElement就可以进行代码跳转以及文件搜索导航了。

    图片

    生成android.ipr文件的详细步骤。

    1. 将excluded-paths文件拷贝到Android源码根目录,比如: /home/tanfh/data/code/android/
    2. source build/envsetup.sh
    3. mmma development/tools/idegen/会生成idegen.jar,google默认的jar不会过滤掉不需要的文件和目录,所以笔者更改了一下源码,生成了一个自己的jar。
    4. 执行development/tools/idegen/idegen.sh,会生成如下三个文件:
      1. android.iml
      2. android.ipr 用Android Studio打开这个文件。
      3. android.iws
    5. 打开Android Studio->File->Open 打开生成的android.ipr文件。
    展开全文
  • Android平台特性

    千次阅读 2018-08-17 11:14:40
    Android平台采用了整合的策略思想,包括底层Linux操作系统、中间层的中间件和上层的Java应用程序。下面我把Android的特性及其架构体系结构总结一下。 一、Android的平台特性  Android平台有如下特性:  1. 应用...

    Android平台采用了整合的策略思想,包括底层Linux操作系统、中间层的中间件和上层的Java应用程序。下面我把Android的特性及其架构体系结构总结一下。

    一、Android的平台特性

      Android平台有如下特性:

      1. 应用程序框架支持组件的重用与替换。

      这样我们可以把系统中不喜欢的应用程序删除,安装我们喜欢的应用程序。

      2. Dalvik虚拟机专门为移动设备进行了优化。

      Android应用程序将由Java编写、编译的类文件通过DX工具转换成一种后缀名为.dex的文件来执行。Dalvik虚拟机是基于寄存器的,相对于Java虚拟机速度要快很多。

      3. 内部集成浏览器基于开源的WebKit引擎。

      有了内置的浏览器,这将意味着WAP应用的时代即将结束,真正的移动互联网时代已经来临,手机就是一台“小电脑”,可以在网上随意遨游。

      4. 优化的图形库包括2D和3D图形库,3D图形库基于OpenGL ES 1.0。

      强大的图形库给游戏开发带来福音。在3G最为重要的的应用莫过于手机上网和手机游戏。

      5. SQLite用作结构化的数据存储。

      6. 多媒体支持包括常见的音频、视频和静态印象文件格式

      如MPEG4、H.264、MP3、AAC、AMR、JGP、PNG、GIF。

      7. GSM电话(依赖于硬件)。

      8. 蓝牙(Bluetooth)、EDGE、3G、WiFi(依赖于硬件)。

      9. 照相机、GPS、指南针和加速度计(依赖于硬件)。

      10. 丰富的开发环境包括设备模拟器、调试工具、内存及性能分析图表和Eclipse集成的开发环境插件。

      Google提供了Android开发包SDK,其中包含了大量的类库和开发工具,并且针对Eclipse的可视化开发插件ADT。

    二、Android平台架构


    Android 操作系统的体系结构

      从上图我们可以看出,Android操作系统的体系结构可分为4层,由上到下依次是应用程序、应用程序框架、核心类库和Linux内核,其中第三层还包括Android运行时的环境。下面分别来讲解各个部分。

      1. 程序应用

      Android 连同一个核心应用程序包一起发布,该应用程序包包括E-mail客户端、SMS短消息程序、日历、地图、浏览器、联系人管理程序等。所有的应用程序都是用Java编写的。

      2. 应用程序框架

      开发者完全可以访问核心应用程序所使用的API框架。该应用程序框架架构用来简化组件软件的重用,任何一个应用程序都可以发布它的功能块并且任何其他的应用程序都可以使用其所发布的功能块(不过得遵循框架的安全性限制)。该应用程序重用机制使得组件可以被用户替换。

      以下所有的应用程序都由一系列的服务和系统组成,包括:

      1)一个可扩展的视图(Views)可以用来创建应用程序,包括列表(lists)、网络(grids)、文本框(text boxes)、按钮(buttons),甚至是一个可嵌入的Web浏览器。

      2)内容管理器(Content Providers)使得应用程序可以访问另一个应用程序的数据(如联系人数据库),或者共享它们自己的数据。

      3)一个资源管理器(Resource Manager)提供非代码资源的访问,如本地字符串、图形和分层文件(layout files)。

      4)一个通知管理器(Notification Manager)使得应用程序可以在状态栏中显示客户通知信息。

      5)一个活动类管理器(Activity Manager)用来管理应用程序生命周期并提供常用的导航回退功能。

      3. Android程序库

      Android包括一个被Android系统中各种不同组件所使用的C/C++集库。该库通过Android应用程序框架为开发者提供服务。

      以下是一些主要的核心库:

      1)系统C库:一个从BSD继承来的标准C系统函数库(libc),专门为基于Embedded Linux的设备定制。

      2)媒体库:基于PacketVideo OpenCORE;该库支持录放,并且可以录制许多流行的音频视频格式,还有静态映像文件包括MPEG4、H.264、MP3、AAC、JPG、PNG。

      3)Surface Manager:对显示子系统的管理,并且为多个应用程序提供2D和3D图层的无缝融合。

      4)LibWebCore:一个最新的Web浏览器引擎,用来支持Android浏览器和一个可嵌入的Web视图。

      5)SGL:一个内置的2D图形引擎。

      6)3D libraries:基于OpenGL ES 1.0 APIs实现;该库可以使用硬件3D加速(如果可用)或者使用高度优化的3D软加速。

      7)FreeType:位图(bitmap)和向量(vector)字体显示。

      8)SQLite:一个对于所以应用程序可用、功能强劲的轻型关系型数据库引擎。

      4. Android运行库

      Android包括了一个核心库,该核心库提供了Java编程语言核心库的大多数功能。

      每一个Android应用程序都在它自己的进程中运行,都拥有一个独立的Dalvik虚拟机实例。Dalvik是针对同时高效地运行多个VMs实现的。Dalvik虚拟机执行.dex的Dalvik可执行文件,该格式文件针对最小内存使用做了优化。该虚拟机是基于寄存器的,所有的类都是经由Java汇编器编译,然后通过SDK中的DX工具转化成.dex格式由虚拟机执行。

      Dalvik虚拟机依赖于Linux的一些功能,比如线程机制和底层内存管理机制。

      5. Linux内核

      Android的核心系统服务依赖于Linux内核,如安全性、内存管理、进程管理、网络协议栈和驱动模型。Linux内核也同时作为硬件和软件栈之间的硬件抽象层。

    相关文档:Google工程师多图详解Android架构


    安卓操作系统有什特点?

      Android的系统架构和其它操作系统一样,采用了分层的架构。android分为四个层,从高层到低层分别是应用程序层、应用程序框架层、系统运行库层和linux核心层。
      Android是以Linux为核心的手机操作平台,作为一款开放式的操作系统,随着Android的快速发展,如今已允许开发者使用多种编程语言来开发Android应用程序,而不再是以前只能使用Java开发Android应用程序的单一局面,因而受到众多开发者的欢迎,成为真正意义上的开放式操作系统。
      在Android中,开发者可以使用Java作为编程语言来开发应用程序,也可以通过NDK使用C/C++作为编程语言来开发应用程序,也可使用SL4A来使用其他各种脚本语言进行编程(如:python、lua、tcl、php等等),还有其他诸如:Qt(qt for android)、Mono(mono for android)等一些著名编程框架也开始支持Android编程,甚至通过MonoDroid,开发者还可以使用C#作为编程语言来开发应用程序。另外,谷歌还在2009年特别发布了针对初学者的Android Simple语言,该语言类似Basic语言。而在网页编程语言方面,JavaScript,ajax,HTML5,jquery、sencha、dojo、mobl、PhoneGap等等都已经支持Android开发。
      而在Android系统底层方面,Android使用C/C++作为开发语言。
     

    Android架构设计的思想与原则是什?

    rlei分析了Android的设计哲学:
    理解好Intent,就可以理解Android哲学(所有应用生来平等)的一部分。举个简单的例子,iOS里面应用要集成SNS如facebook/twitter/sina weibo等,都需要应用自己实现(iOS5也只是集成twitter一家);Android上只需要广播一个share内容的intent。从理解Intent如何工作开始,你就在慢慢理解Activity Manager, Package Manager, Services这些Android的重要组件是如何工作的。
    另外Binder是Android架构里非常核心的一块。Android基于Intent的消息传递和组件/应用解耦,下面的基础都是Binder IPC。在这一点上,Android实际上是光荣的传承了BeOS和Palm OS 6(悲催的OS6…)未能发扬光大的一部分。
    MVC(Content Provider, Activity, Layout, Adapters)这个比较基础,也不算Android特有的。
    Content Provider对数据访问的抽象也是比较有意思的一块。理想情况下,content provider可以让客户端用URI以语义化的方式访问数据(URI本身即表示数据层次结构和查询条件),而下面数据库表的结构可以任意变动,不影响客户端代码。当然实做的时候content provider还是会被各种复杂的where子句暴露出SQL的实现细节
    至于Android的权限管理,其实比较简单,主要是利用现成的Linux安全模型,进程之间相互隔离。API级别的权限管理和JVM类似。
    Billy Cui重点解析了权限系统的设计:
    Android的权限系统是基于Linux,但又增加了很多自己的控制模块。
    总体上来说,其分为以下几部分权限系统:
    1. userid : 继承于linux,对于多个app,通过shareuid的方式可以使用同一个userid,主要承担一些目录访问权限之类的工作,比如私有目录只能由同一uid应用访问。
    2. 安装level:system level or app level,这个是根据应用的安装位置决定的,在system/app下安装的应用就是system level,在权限访问中会得到更多的权限,比如静默安装应用的权限等。
    3. permission : 这个是最主要的权限控制,一般开发者开发应用主要是接触这个部分,在这部分中,会根据应用在AndroidManifest.xml中声明的use-permission而在访问相应api或资源时判断其是否有访问权限,比如常用的android.permission.INTERNET等。
    4. signature: 签名,是Android权限系统中的重要组成部分,对于系统签名的应用,会有一些特殊的功能,而shareuid等特性也是需要同一签名作为基础。此外,permission在设置/自定义其权限时也经常会使用到签名,比如控制只有我自己的应用才可以访问我自己定义的公开API。
    除此以外,其实Android在uid的里面设置了一些预定义有特殊功能的uid,比如system/media等,在配置其system level的services的时候会用到。



    展开全文
  • Android平台漏洞挖掘与利用

    千人学习 2015-10-30 15:33:25
    Android平台漏洞挖掘与利用视频教程,该课程将介绍几类漏洞的特征以及利用方法。本次课程将以Qualcomm平台上的CVE-2013-6123漏洞为例,介绍如何找出危险的数据交换代码,以及如何稳定利用任意地址写漏洞。也将介绍...
  • 要想将Python解释器移植到Android平台,首先要做的就是将Python源码用NDK工具交叉编译为Android平台的二进制库。目前官方是没有提供对Android平台的支持的,但新的版本已经在考虑对Android提供支持,参考文档 API 24...

    Android 平台的Python——基础篇(一)
    Android 平台的Python——JNI方案(二)
    Android 平台的Python——CLE方案实现(三)
    Android 平台的Python——第三方库移植
    Android 平台的Python——编译Python解释器

    要想将Python解释器移植到Android平台,首先要做的就是将Python源码用NDK工具交叉编译为Android平台的二进制库。目前官方是没有提供对Android平台的支持的,但新的版本已经在考虑对Android提供支持,参考文档 API 24 is the first version where the adb shell is run on the emulator as a shell user instead of the root user previously, and the first version that supports arm64.

    Android不是常见的Linux系统,只有Linux内核是共享的,其他一切都是不同的,它使用的C标准库是Bionic,与glibc有很大差异,因此直接使用NDK编译源码会报错。

    上一篇博客已经谈到了关于Python第三方库移植的问题,但是 CrytaxNDK中的Python解释器存在一些问题,未支持SSL,导致无法访问HTTPS,这次我们先使用CrytaxNDK重新编译Python

    在Linux平台交叉编译Python

    首先需要搭建一个Linux环境,推荐使用Ubuntu,这里关于虚拟机安装Ubuntu就不说了

    步骤一

    设置环境。下载CrytaxNDK的Linux版本,并解压到某个目录。需要说明一下,这里可以不用将CrytaxNDK加入到环境变量,也可以加入,方便以后开发使用
    输入命令,配置环境变量
    sudo vim /etc/profile
    将以下内容添加到文件末尾,其中NDK_DIR指向解压后的CrytaxNDK根目录,请替换成自己的实际目录

    export NDK_DIR=/home/CrystaX/crystax-ndk-10.3.2
    export PATH=$PATH:$NDK_DIR
    export NDK_MODULE_PATH=$NDK_DIR/sources
    

    完成后,输入命令source /etc/profile更新环境变量,使之生效。

    步骤二

    下载源码。到官网下载Python3.5的源码,建议下载一个稳定版。将下载之后的源码解压到系统的某个目录,并设置一个全局环境变量,指向Python源码根目录。

    export PYTHON_DIR=/home/Python-3.5.1
    
    步骤三

    下载OpenSSL源码。由于CrytaxNDK没有带openssl,所以我们必须手动添加。这里我们可以取个巧,直接下载别人编译好的so,懒得去搞环境自己编译。下载地址 这个里面倒是提供了二进制so,但是没提供头文件,所以还是得下载OpenSSL源码
    按照下图路径,放入CrytaxNDK根目录下面的sources/openssl/1.0.1p/路径下,头文件放入include中,so放入libs中的对应的CPU架构目录下
    在这里插入图片描述

    步骤四

    执行编译。进入到CrytaxNDK根目录下面的build/tools/目录下,执行命令

    ./build-target-python.sh --ndk_dir=$NDK_DIR --abis=armeabi -j5 --verbose $PYTHON_DIR
    

    实际上CrytaxNDK已经提供了一个简单的编译脚本,可以输入./build-target-python.sh --help查看一下选项

    Valid options (defaults are in brackets):
    --help                   Print this help.
    --verbose                Enable verbose mode.
    --dryrun                 Set to dryrun mode.
    --package-dir=<path>     Put prebuilt tarballs into <path>
    --ndk-dir=<path>         Specify NDK root path for the build
    --build-dir=<path>       Specify temporary build dir
    --abis=<list>            Specify list of target ABIs [armeabi armeabi-v7a x86 mips armeabi-v7a-hard arm64-v8a x86_64 mips64]
    -j<number>               Use <number> parallel build jobs
    

    编译完成之后,即在crystax-ndk-10.3.2/sources/python/3.5/下生成so和相关标准库,看一下modules目录,已经产生了_ssl.so,按照上篇博客,添加_ssl.so,即可愉快的访问HTTPS了。在本博客的最后,我会添加已经编译好的so,但是所有编译的so都未进行回归测试,不保证支持所有的Python特性和库调用。

    在Windows平台上编译

    使用CrytaxNDK编译Python是比较容易的,因为 CrystaX NDK更接近普通的Linux glibc。实际上不是很推荐在Windows上编译,并不是不能编译,因为交叉编译和你所在的平台并没有太大关系,只要有交叉编译器。我们使用NDK 虽然和编译平台关系不大,但是却和项目构建工具密切相关,因此使用Windows编译,需要额外的做更多事。Python项目只提供了autoconf 和VS的项目文件,而autoconf /automake实际上是执行一系列的shell命令,最终生成一个Makefile文件,最终仍然是使用make工具进行编译。而我们想要在Windows上编译,更为可行的办法是使用Google提供的改进后的Android.mk脚本。不推荐使用通过在Windows上安装模拟shell命令环境的工具实现编译。

    现在简单说一下编译方案,我们可以根据build-target-python.sh脚本,改写出Android.mk,然后使用ndk-build命令进行编译即可。
    以下是我用来编译Python core 的 Android.mk,其中将MY_PYTHON_SRC_ROOT变量设置为你本地的Python3.5的源码根路径,建议写绝对路径。我在其中定义了几个空的宏,DPREFIX、DEXEC_PREFIX、DVPATH、DPYTHONPATH等,否则会报错。这几个宏是用来设置Python默认的一些加载路径的,但是在嵌入解释器的时候,则无意义。在源码getpath.c中已经进行了注释说明,因此我们在使用之前,一定要先调用Py_SetPath设置加载路径。
    在这里插入图片描述

    LOCAL_PATH := $(call my-dir)
    MY_PYTHON_SRC_ROOT := E:/PythonBuild/py35/src
    include $(CLEAR_VARS) 
    LOCAL_MODULE := python3.5m
    LOCAL_C_INCLUDES := $(MY_PYTHON_SRC_ROOT)/Include
    LOCAL_CFLAGS := -DSOABI=\"cpython-3.5m\" -DPy_BUILD_CORE -DPy_ENABLE_SHARED -DPREFIX=\"\" -DEXEC_PREFIX=\"\" -DVPATH=\"\" -DPYTHONPATH=\"\" -DVERSION=\"3.5.1\"
    LOCAL_LDLIBS := -lz
    LOCAL_SRC_FILES := ../config.c \
      \
      $(MY_PYTHON_SRC_ROOT)/Python/random.c \
      $(MY_PYTHON_SRC_ROOT)/Python/_warnings.c \
      $(MY_PYTHON_SRC_ROOT)/Python/asdl.c \
      $(MY_PYTHON_SRC_ROOT)/Python/ast.c \
      $(MY_PYTHON_SRC_ROOT)/Python/bltinmodule.c \
      $(MY_PYTHON_SRC_ROOT)/Python/ceval.c \
      $(MY_PYTHON_SRC_ROOT)/Python/codecs.c \
      $(MY_PYTHON_SRC_ROOT)/Python/compile.c \
      $(MY_PYTHON_SRC_ROOT)/Python/dynamic_annotations.c \
      $(MY_PYTHON_SRC_ROOT)/Python/dynload_shlib.c \
      $(MY_PYTHON_SRC_ROOT)/Python/errors.c \
      $(MY_PYTHON_SRC_ROOT)/Python/fileutils.c \
      $(MY_PYTHON_SRC_ROOT)/Python/formatter_unicode.c \
      $(MY_PYTHON_SRC_ROOT)/Python/frozen.c \
      $(MY_PYTHON_SRC_ROOT)/Python/future.c \
      $(MY_PYTHON_SRC_ROOT)/Python/getargs.c \
      $(MY_PYTHON_SRC_ROOT)/Python/getcompiler.c \
      $(MY_PYTHON_SRC_ROOT)/Python/getcopyright.c \
      $(MY_PYTHON_SRC_ROOT)/Python/getopt.c \
      $(MY_PYTHON_SRC_ROOT)/Python/getplatform.c \
      $(MY_PYTHON_SRC_ROOT)/Python/getversion.c \
      $(MY_PYTHON_SRC_ROOT)/Python/graminit.c \
      $(MY_PYTHON_SRC_ROOT)/Python/import.c \
      $(MY_PYTHON_SRC_ROOT)/Python/importdl.c \
      $(MY_PYTHON_SRC_ROOT)/Python/marshal.c \
      $(MY_PYTHON_SRC_ROOT)/Python/modsupport.c \
      $(MY_PYTHON_SRC_ROOT)/Python/mysnprintf.c \
      $(MY_PYTHON_SRC_ROOT)/Python/mystrtoul.c \
      $(MY_PYTHON_SRC_ROOT)/Python/peephole.c \
      $(MY_PYTHON_SRC_ROOT)/Python/pyarena.c \
      $(MY_PYTHON_SRC_ROOT)/Python/pyctype.c \
      $(MY_PYTHON_SRC_ROOT)/Python/pyfpe.c \
      $(MY_PYTHON_SRC_ROOT)/Python/pyhash.c \
      $(MY_PYTHON_SRC_ROOT)/Python/pylifecycle.c \
      $(MY_PYTHON_SRC_ROOT)/Python/pymath.c \
      $(MY_PYTHON_SRC_ROOT)/Python/pytime.c \
      $(MY_PYTHON_SRC_ROOT)/Python/pystate.c \
      $(MY_PYTHON_SRC_ROOT)/Python/pystrcmp.c \
      $(MY_PYTHON_SRC_ROOT)/Python/pystrhex.c \
      $(MY_PYTHON_SRC_ROOT)/Python/pystrtod.c \
      $(MY_PYTHON_SRC_ROOT)/Python/dtoa.c \
      $(MY_PYTHON_SRC_ROOT)/Python/Python-ast.c \
      $(MY_PYTHON_SRC_ROOT)/Python/pythonrun.c \
      $(MY_PYTHON_SRC_ROOT)/Python/structmember.c \
      $(MY_PYTHON_SRC_ROOT)/Python/symtable.c \
      $(MY_PYTHON_SRC_ROOT)/Python/sysmodule.c \
      $(MY_PYTHON_SRC_ROOT)/Python/thread.c \
      $(MY_PYTHON_SRC_ROOT)/Python/traceback.c \
      \
      $(MY_PYTHON_SRC_ROOT)/Parser/acceler.c \
      $(MY_PYTHON_SRC_ROOT)/Parser/bitset.c \
      $(MY_PYTHON_SRC_ROOT)/Parser/firstsets.c \
      $(MY_PYTHON_SRC_ROOT)/Parser/grammar.c \
      $(MY_PYTHON_SRC_ROOT)/Parser/grammar1.c \
      $(MY_PYTHON_SRC_ROOT)/Parser/listnode.c \
      $(MY_PYTHON_SRC_ROOT)/Parser/metagrammar.c \
      $(MY_PYTHON_SRC_ROOT)/Parser/myreadline.c \
      $(MY_PYTHON_SRC_ROOT)/Parser/node.c \
      $(MY_PYTHON_SRC_ROOT)/Parser/parser.c \
      $(MY_PYTHON_SRC_ROOT)/Parser/parsetok.c \
      $(MY_PYTHON_SRC_ROOT)/Parser/tokenizer.c \
      \
      $(MY_PYTHON_SRC_ROOT)/Objects/abstract.c \
      $(MY_PYTHON_SRC_ROOT)/Objects/accu.c \
      $(MY_PYTHON_SRC_ROOT)/Objects/boolobject.c \
      $(MY_PYTHON_SRC_ROOT)/Objects/bytes_methods.c \
      $(MY_PYTHON_SRC_ROOT)/Objects/bytearrayobject.c \
      $(MY_PYTHON_SRC_ROOT)/Objects/bytesobject.c \
      $(MY_PYTHON_SRC_ROOT)/Objects/capsule.c \
      $(MY_PYTHON_SRC_ROOT)/Objects/cellobject.c \
      $(MY_PYTHON_SRC_ROOT)/Objects/classobject.c \
      $(MY_PYTHON_SRC_ROOT)/Objects/codeobject.c \
      $(MY_PYTHON_SRC_ROOT)/Objects/complexobject.c \
      $(MY_PYTHON_SRC_ROOT)/Objects/descrobject.c \
      $(MY_PYTHON_SRC_ROOT)/Objects/dictobject.c \
      $(MY_PYTHON_SRC_ROOT)/Objects/enumobject.c \
      $(MY_PYTHON_SRC_ROOT)/Objects/exceptions.c \
      $(MY_PYTHON_SRC_ROOT)/Objects/fileobject.c \
      $(MY_PYTHON_SRC_ROOT)/Objects/floatobject.c \
      $(MY_PYTHON_SRC_ROOT)/Objects/frameobject.c \
      $(MY_PYTHON_SRC_ROOT)/Objects/funcobject.c \
      $(MY_PYTHON_SRC_ROOT)/Objects/genobject.c \
      $(MY_PYTHON_SRC_ROOT)/Objects/iterobject.c \
      $(MY_PYTHON_SRC_ROOT)/Objects/listobject.c \
      $(MY_PYTHON_SRC_ROOT)/Objects/longobject.c \
      $(MY_PYTHON_SRC_ROOT)/Objects/memoryobject.c \
      $(MY_PYTHON_SRC_ROOT)/Objects/methodobject.c \
      $(MY_PYTHON_SRC_ROOT)/Objects/moduleobject.c \
      $(MY_PYTHON_SRC_ROOT)/Objects/namespaceobject.c \
      $(MY_PYTHON_SRC_ROOT)/Objects/object.c \
      $(MY_PYTHON_SRC_ROOT)/Objects/obmalloc.c \
      $(MY_PYTHON_SRC_ROOT)/Objects/odictobject.c \
      $(MY_PYTHON_SRC_ROOT)/Objects/rangeobject.c \
      $(MY_PYTHON_SRC_ROOT)/Objects/setobject.c \
      $(MY_PYTHON_SRC_ROOT)/Objects/sliceobject.c \
      $(MY_PYTHON_SRC_ROOT)/Objects/structseq.c \
      $(MY_PYTHON_SRC_ROOT)/Objects/tupleobject.c \
      $(MY_PYTHON_SRC_ROOT)/Objects/typeobject.c \
      $(MY_PYTHON_SRC_ROOT)/Objects/unicodectype.c \
      $(MY_PYTHON_SRC_ROOT)/Objects/unicodeobject.c \
      $(MY_PYTHON_SRC_ROOT)/Objects/weakrefobject.c \
      \
      $(MY_PYTHON_SRC_ROOT)/Modules/audioop.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/_bisectmodule.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/_codecsmodule.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/_collectionsmodule.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/_csv.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/_functoolsmodule.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/hashtable.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/_heapqmodule.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/_json.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/_localemodule.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/_lsprof.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/_math.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/_pickle.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/_randommodule.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/_sre.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/_struct.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/_weakref.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/arraymodule.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/atexitmodule.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/binascii.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/cmathmodule.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/_datetimemodule.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/errnomodule.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/faulthandler.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/fcntlmodule.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/gcmodule.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/getpath.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/itertoolsmodule.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/main.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/mathmodule.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/md5module.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/mmapmodule.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/_opcode.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/_operator.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/parsermodule.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/posixmodule.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/_posixsubprocess.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/pwdmodule.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/rotatingtree.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/sha1module.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/sha256module.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/sha512module.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/signalmodule.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/_stat.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/symtablemodule.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/_threadmodule.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/_tracemalloc.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/termios.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/timemodule.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/xxsubtype.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/zipimport.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/zlibmodule.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/getbuildinfo.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/cjkcodecs/_codecs_cn.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/cjkcodecs/_codecs_hk.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/cjkcodecs/_codecs_iso2022.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/cjkcodecs/_codecs_jp.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/cjkcodecs/_codecs_kr.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/cjkcodecs/_codecs_tw.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/cjkcodecs/multibytecodec.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/_io/_iomodule.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/_io/textio.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/_io/iobase.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/_io/bufferedio.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/_io/stringio.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/_io/bytesio.c \
      $(MY_PYTHON_SRC_ROOT)/Modules/_io/fileio.c
      
    include $(BUILD_SHARED_LIBRARY)
    

    我们创建一个用于编译的目录build,在其中创建jni目录、libs目录,然后添加我们的Android.mk文件,再创建一个Application.mk文件,添加以下内容

    APP_PLATFORM = android-21
    APP_ABI := armeabi
    

    接下来将crystax-ndk-10.3.2\build\tools\build-target-python\ 目录下 config.c拷贝到jni目录下,可以看到crystax-ndk-10.3.2\build\tools\build-target-python\下的pyconfig.h实际上是个空文件,因此需要将我提供的pyconfig.h拷贝到Python源码根目录下的Include目录中。
    最后就是编译了,cd到我们build根目录下,执行ndk-build命令即可生成 libpython3.5m.so,亲测可用。关于Python的modules编译,按照该思路,编写Android.mk脚本即可,至于怎么编写mk文件,慢慢参照 build-target-python.sh,本篇博客不在继续讨论。另外怎么设置Windows上的CrytaxNDK环境省略,参照之前的博客。
    在这里插入图片描述

    最后谈一谈其他的编译Python so的方式,因为QPython早已经成功的在Android上运行了Python,我们完全可以直接参照QPython的方式
    我们进入QPython的GitHub QPython
    在这里插入图片描述
    实际上,QPython这里的编译是来自与另一开源的编译Python的项目,而最老的项目出处,应该来自于这个 项目,之后很多人fork,逐渐演化为使用Python脚本交叉编译。
    我们在Ubuntu上进行,Mac的我未测试。
    首先 下载NDK r16 beta 2,并配置好环境变量$ANDROID_NDK
    其次使用git clone https://github.com/qpython-android/qpython3-toolchain.git 将该交叉编译脚本拉下来。
    有一点需要注意,使用他的脚本编译Python时,本地Ubuntu上也要先装好对应的Python版本,比如我要编译Python3.6,那么我先要在Ubuntu上装好3.6。另外一个需要注意的就是网要好,最后先配上代理,因为一套编译脚本实际上是用Python写的,会在线下载需要的各种代码,包括Python源码,网不好,下载需要很久。

    准备好这些后,还不能在目录下执行make,我们先进入pybuild目录,编辑一下env.py文件,指定CPU架构,android_api_level

    target_arch = 'arm'
    android_api_level = 21
    

    这时已经可以愉快的执行make命令了,然后就是漫长的等待,完成后,进入qpython3-toolchain/src/cpython 下即可找到二进制,唯一比较坑的是,它生成的是libpython3.6m.a的静态库。通过阅读了整个交叉编译脚本后,我发现这套Python脚本只是替换了原来的shell脚本而已,仍然是通过标准的Linux下的安装步骤编译的。即通过执行./configrue生成Makefile,然后编译。那么我们只需增加一个选项即可编译出动态库。
    进入qpython3-toolchain/pybuild/packages/目录下,找到python.py文件,添加如下内容

    --enable-shared=yes
    

    在这里插入图片描述

    修改完保存退出,再次make,就可以愉快的编译出 libpython3.6m.so
    最后说一下,编译完之后modules里面的那些so在 qpython3-toolchain/src/cpython/build/lib.linux-arm-3.6 目录下
    在这里插入图片描述

    博客 本章资源下载链接

    关注个人公众号:编程之路从0到1

    编程之路从0到1

    展开全文
  • android平台下OpenGL ES 3.0从零开始 android平台下OpenGL ES 3.0绘制纯色背景 android平台下OpenGL ES 3.0绘制圆点、直线和三角形 android平台下OpenGL ES 3.0绘制彩色三角形 android平台下OpenGL ES 3.0从矩形中看...
  • Android平台的崩溃捕获机制及实现

    千人学习 2015-12-31 10:20:10
    Android平台的崩溃捕获机制视频教程,该课程主要对Java崩溃和Native崩溃的捕获机制进行分析,并结合简单的实例演示实现方法。 讲师介绍:贾志凯,Testin崩溃分析项目研发工程师,负责客户端SDK相关技术研发工作。5年...
  • [019] Android平台调用WebService详解

    万次阅读 多人点赞 2011-05-18 00:06:00
    上篇文章已经对Web Service及其相关知识进行了介绍(Android...本文将通过一个简单的示例讲解和演示Android平台的Web Service开发。 Ksoap2-android简介  在Android平台调用Web Service需要依赖于第三方类库ksoap
  • Android_Page Curl:Android平台上的翻书翻页 我在之前介绍了一种Android平台上的翻书翻页第三方开源实现,参见附录文章1。现在再介绍一篇第三方开源的翻书翻页开源实现Android_Page Curl,其在github上的项目主页...
  • FFmpeg的Android平台移植—编译篇

    万次阅读 多人点赞 2014-04-01 19:11:20
    FFmpeg的Android平台移植—编译篇 Dennis Hu 2014年3月28日 摘要:本文主要介绍将FFmpeg音视频编解码库移植到Android平台上的编译和基本测试过程。 环境准备: Ubuntu12.04 TLS android-ndk-r9d-linux-x86_64.tar.bz...
  • android平台下OpenGL ES 3.0从零开始

    千次阅读 2018-11-04 15:33:48
    OpenGL ES对Android平台的支持情况 OpenGL ES 3.0概述 OpenGL ES 3.0图形管线图 顶点着色器 片段着色器 图元装配 光栅化 逐片段操作 虚拟机和OpenGL ES 3.0的数据传输 OpenGL ES对Android平台的支持情况 ...
  • android平台下OpenGL ES 3.0从零开始 android平台下OpenGL ES 3.0绘制纯色背景 android平台下OpenGL ES 3.0绘制圆点、直线和三角形 android平台下OpenGL ES 3.0绘制彩色三角形 android平台下OpenGL ES 3.0从矩形中看...
  • 编译Android平台的opencv

    千次阅读 2017-04-17 15:02:15
    编译Android平台的opencv编译流程第一步:安装Cmake 第二步: 编写脚本configure.bat文件cmake -G "Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=..\..\android\android.toolchain.cmake ..\..\.. -DANDROID_NDK="D:\...
  • 第四章、Android编译系统与定制Android平台系统 4.1Android编译系统Android的源码由几十万个文件构成,这些文件之间有的相互依赖,有的又相互独立,它们按功能或类型又被放到不同目录下,对于这个大的一个工程,...
  • SDL2.0 Android 平台移植

    千次阅读 2018-04-23 16:45:26
    最近做一个项目用到了SDL和ffmpeg,去网上找了一些SDL移植的例子,发现SDL2.0.8版本稍微有些改动JNI接口实现的方式有些不同,这篇文章主要是再详细的记录一下SDL 向android平台的移植过程。1、首先去这个链接下载...
  • 什么是Android——Android平台简介

    万次阅读 2011-03-10 17:52:00
    什么是Android ——Android平台简介 <br /> <br />Keyword: Google Android,Linux内核,开源,应用领域,开放手机联盟(Open Handset Alliance) <br />   在网上看到有“Android平台”和...
  • Android平台交叉编译流程

    千次阅读 2017-07-04 21:36:54
    一: 当我们在Android平台上开发一些软件的时候,有时不可避免的要用到一些用c/c++所编写的库。有些库有大神们已经封装好了在特定平台上对应的api,我们直接调用就可以,但是更多的库需要我们自己根据自己所需的特定...
  • Android 平台下的原生 Markdown 解析器

    千次阅读 2016-11-08 10:53:11
    Android 平台下的原生 Markdown 解析器
  • Android平台的so注入--LibInject

    千次阅读 2016-12-27 14:38:29
    大牛古河在看雪论坛分享的Android平台的注入代码,相信很多搞Android安全的同学应该都看过。刚接触Android平台的逆向时,我也下载了LibInject代码并且仔细的阅读和分析过,见我前面的博文《Android的so库注入》。我...
  • 一般项目版本管理,会有多个svn分支,拉新的svn分支后,打开工程默认以PC为平台,如果工程比较大的话,需要等好长一段时间,等所有资源都编译完之后,然后再手动在BuildSettings中切换成Android平台,然后又要等好长...
  • Android平台Camera实时滤镜实现方法

    千次阅读 2018-05-27 17:38:23
    Android+JNI+OpenGL开发自己的美图秀秀 Android平台Camera实时滤镜实现方法探讨(十一)--实时美颜滤镜 Android平台Camera实时滤镜实现方法探讨(十)--代码地址以及简介(20160118更新) [Android开发]LinearLayout...
  • Android 平台点对点音视频对讲

    千次阅读 2019-08-15 11:42:09
    Communication Android平台 点对点 音视频...本项目提供Android平台点对点音视频对讲功能,项目的基本架构如下: 1. Android Camera2 API 采集预览视频 2. MediaCodec 进行硬编码,编码成h264视频文件 3. AudioRecord...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 91,722
精华内容 36,688
关键字:

android平台