这里是一个在android上运行django的例子,通常django是从命令行运行的,如果在android中运行,需要从java代码中加载python解释器,运行django脚本,需要修改一下django的启动参数。
该例子使用python2.7,首先需要提取django,在windows中安装diango,安装完成之后,打包目录“\Lib\site-ackages\Django-1.10.5-py2.7.egg\django”为一个zip,放到android工程的assets目录下面;创建mysite站点,将站点打包成为mysite.zip,放到android工程的assets目录下面。
1. 创建工程
该例子代码使用eclipse开发,可以直接导入到android studio中。
在libs目录下添加共享库文件:
在assets目录下添加python扩展库,django.zip和mysite.zip
2. 修改django
Django加载需要一定时间,加载完成之后通知界面,需要设置共享变量MainActivity,该变量提供函数OnDJangoInitFinish,函数由java编写,可以由python调用。创建一个空的python module文件” starglobal.py”管理python变量
public void OnDJangoInitFinish()
{
Message message = handler.obtainMessage();
message.what = 0;
message.obj = null;
handler.sendMessage(message);
}
修改
runserver.py,
在
django\ core\management\commands
目录下
def inner_run(self, *args, **options):
….
try:
import starglobal
starglobal.MainActivity.OnDJangoInitFinish() # notify host
handler = self.get_handler(*args, **options)
run(self.addr, int(self.port), handler,
ipv6=self.use_ipv6, threading=threading)
修改站点的
manage.py
,
django
加载之后会进入循环,因此为了避免阻止界面线程,在
python
中创建一个线程运行。在
manage.py
运行最后,进入
cle
的消息循环,界面创建一个线程初始化并加载
django
。
#!/usr/bin/env python
import os
import sys
import traceback
import thread
import time
def doit(val):
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
try:
from django.core.management import execute_from_command_line
except ImportError:
# The above import may fail for some other reason. Ensure that the
# issue is really that Django is missing to avoid masking other
# exceptions on Python 2.
try:
import django
except ImportError:
traceback.print_exc()
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
)
raise
execute_from_command_line(['manage.py', 'runserver','--noreload'])
if __name__ == "__main__":
try:
import starglobal
starglobal.MainActivity = MainActivity
thread.start_new_thread(doit,(0,))
while True :
while libstarpy._SRPDispatch(False) == True :
pass
libstarpy._SRPUnLock()
time.sleep(0.01)
libstarpy._SRPLock()
except Exception :
traceback.print_exc()
3. 初始化python解释器,加载Django
a.将python2.7.zip拷贝到"/data/data/"+getPackageName()+"/files"目录下
File destDir = new File("/data/data/"+getPackageName()+"/files");
if(!destDir.exists())
destDir.mkdirs();
java.io.File python2_7_libFile = new java.io.File("/data/data/"+getPackageName()+"/files/python2.7.zip");
if( !python2_7_libFile.exists() ){
try{
copyFile(this,"python2.7.zip",null);
}
catch(Exception e){
}
}
b. 将django.zip和mysite.zip解压到"/data/data/"+getPackageName()+"/files"目录下
try{
AssetManager assetManager = getAssets();
InputStream dataSource = assetManager.open("django.zip");
unzip(dataSource, "/data/data/"+getPackageName()+"/files",false );
dataSource.close();
dataSource = assetManager.open("mysite.zip");
unzip(dataSource, "/data/data/"+getPackageName()+"/files",false );
}
catch(Exception e)
{
}
c. 将django运行需要加载的python扩展库拷贝到"/data/data/"+getPackageName()+"/files"目录下
try{
copyFile(this,"zlib.so",null);
copyFile(this,"_json.so",null);
copyFile(this,"_random.so",null);
copyFile(this,"_socket.so",null);
copyFile(this,"_sqlite3.so",null);
copyFile(this,"select.so",null);
copyFile(this,"time.so",null);
copyFile(this,"unicodedata.so",null);
copyFile(this,"datetime.so",null);
copyFile(this,"fcntl.so",null);
copyFile(this,"_struct.so",null);
copyFile(this,"binascii.so",null);
copyFile(this,"_collections.so",null);
copyFile(this,"operator.so",null);
copyFile(this,"itertools.so",null);
copyFile(this,"_functools.so",null);
copyFile(this,"math.so",null);
copyFile(this,"_io.so",null);
copyFile(this,"cStringIO.so",null);
copyFile(this,"_hashlib.so",null);
copyFile(this,"array.so",null);
copyFile(this,"cPickle.so",null);
}
catch(Exception e){
System.out.println(e);
}
d.
初始化
cle
和
python
解释器,设置模块搜索路径,加载
manage.py
/*----init starcore----*/
StarCoreFactoryPath.StarCoreCoreLibraryPath = this.getApplicationInfo().nativeLibraryDir;
StarCoreFactoryPath.StarCoreShareLibraryPath = this.getApplicationInfo().nativeLibraryDir;
StarCoreFactoryPath.StarCoreOperationPath = "/data/data/"+getPackageName()+"/files";
final String LibPath = this.getApplicationInfo().nativeLibraryDir;
final Activity GActivity = this;
new Thread(new Runnable(){
@Override
public void run() {
StarCoreFactory starcore= StarCoreFactory.GetFactory();
StarServiceClass Service=starcore._InitSimple("test","123",0,0);
StarSrvGroupClass SrvGroup = (StarSrvGroupClass)Service._Get("_ServiceGroup");
Service._CheckPassword(false);
/*----run python code----*/
SrvGroup._InitRaw("python",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/python2.7.zip");
pythonPath._Call("insert",0,LibPath);
pythonPath._Call("insert",0,"/data/data/"+getPackageName()+"/files");
pythonPath._Call("insert",0,"/data/data/"+getPackageName()+"/files/django");
pythonPath._Call("insert",0,"/data/data/"+getPackageName()+"/files/mysite");
python._Set("MainActivity", GActivity);
Service._DoFile("python", "/data/data/"+getPackageName()+"/files/mysite/manage.py", "");
}
}).start();
4.运行结果和实例下载
也可以将
django
和
mysite
放在
sd
卡上,此时模块的搜索路径需要相应修改