Introduction
Integrating a web server in android application can increase its flexibility, because it gives more interactive with other terminals. For web server, programmers need write web pages and these pages should be able to interoperate with host application. This article introduces an idea to embed lua in web page as dynamic language at server side and gives an example written based on starcore and SRPSHtmlEnvEngine, which is an embeddable web server supports http get and http post request.
Embedding lua
Lua is a tiny and easily use script language. To embed lua in the web page, we need define a tag for lua script, a server can find the tag, extract the lua code and execute the lua code. In addition, the lua code can call functions defined in host application to do more works.
Defining a tag for lua is simple, for example, “<?lua> <?>” can be used to mark a lua code segment. When the server handle http request, it read the web page, check whether there has lua tag. Then the server execute the code, receive the output from the code, and add the output to the html page.
For example:
<!DOCTYPE html>
<html>
<body>
<h1><?lua echo([[hello from lua]]) /> </h1>
</body>
</html>
The lua code “echo([[hello from lua]])” should be extracted from html page, and executed. Then, the output value “hello from lua” should be inserted to the html page. The result is :
<!DOCTYPE html>
<html>
<body>
<h1>hello from lua</h1>
</body>
</html>
The server engine needs do more work.
1. It should parse http request, create parameters for http get and post request for lua script.
2. It should be able to execute lua script.
3. It should enable lua to call java easily on android. Therefore most functions can be realized by host application.
The next part of this article gives an example to send sms from pc using web browser. It is based on starcore and "SRPSHtmlEnvEngine".
send sms from pc using web browser
1. lua code embedded in the sample page
<?lua>
if( _GET["submit"] == nil ) then
echo(" ")
else
--send sms
print(_POST["number"],_POST["text"]) --output info to console
HostObject:SendSms(_POST["number"],_POST["text"])
echo(hcode("Send sms to ".._POST["number"])) --output result to web page
end
<?>
The _GET and _POST variable are table which is assigned by web server based on http request. The “_GET” is corresponding to http get request, for example, for http://XXX/index.html?a=123&b=456, the _GET variable will be {a=”123”,b=”456”}. The _POST variable is corresponding to http post request, which is extracted from html request body. The code first check whether there has “submit” parameter from request url. If not, then the request is submitted from web browser with message to send. It get send phone number and text, and call SemdSms function of HostObject to send short message. The HostObject is defined in host application, see below.
2. Create project
Create project and add libraries of starcore and SRPSHtmlEnvEngine into the project. As follow,
“libstar_java.so” is the interface of java and “libstarcore.so” is the core share library. “libSRPHtmlEnvEngineBasicModule_android.so” is the library of web server. The file “index.html” in assets directory is the web page. And the “SRPSHtmlEnvEngine.xml” is the service description file of web server. These files should be added to the project.
3. Add user permission in file “AndroidManifest.xml”
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<uses-permission android:name="android.permission.SEND_SMS"></uses-permission>
These permission enables the app to send sms and receive internet request.
4. The main code “MainActivity”
a. Set work path for starcore
StarCoreFactoryPath.StarCoreCoreLibraryPath = "/data/data/"+getPackageName()+"/lib";
StarCoreFactoryPath.StarCoreOperationPath= "/data/data/"+getPackageName()+"/files";
StarCoreFactoryPath.StarCoreShareLibraryPath = "/data/data/"+getPackageName()+"/lib";
StarCoreCoreLibraryPath is the path for “libstarcore.so” and “libstar_java.so”. StarCoreOperationPath is the path of temporary file for starcore. This path may be set to null. StarCoreShareLibraryPath is the path for other share libraries for starcore.
b. Init starore.
starcore= StarCoreFactory.GetFactory();
SrvGroup =starcore._InitSimpleEx(0,0);
SrvGroup._ImportServiceFromXmlBuf(servicestr, true);
SrvGroup._CreateService( ""," test", "123",5,0,0,0,0,0,"" );
Service = SrvGroup._GetService("root","123");
Service._CheckPassword(false);
Using the above code to init starcore. servicestr is service description xml string, which is loaded from assets.
First, we get the object "starcore" through function "GetFactory", and call it's function “_InitSimpleEx” to initialize the starcore middleware. Second, we call the function “_ImportServiceFromXmlBuf” with service description string to import the web server. At last, we call “_CreateService” function to create new starcore service. For details about these functions, please refer to documentation of starcore. For service to be accessible by web server, “_CheckPassword” function must be called with input parameter “false”.
InputStream dataSource = getAssets().open("SRPSHtmlEnvEngine.xml");
int size=dataSource.available();
byte[] buffer=new byte[size];
dataSource.read(buffer);
dataSource.close();
servicestr=new String(buffer);
c. Open web server port
SrvGroup._SetWebServerPort("",8080,100,0);
The first parameter should be set to “”. The second parameter is the port number. The Third parameter is the maximum number of connections simultaneously. The fourth is the maximum post size, unit is Kbytes.
d. Create instance of SHtmlEnvSiteClass to handle web request
StarObjectClass a = Service._GetObject("SHtmlEnvSiteClass")._New()._Assign(new StarObjectClass(){
public Object[] FileOpen(StarObjectClass self,String Name,String RequestPara){
if( Name.equals("/index.html"))
return new Object[]{1,false};
else
return new Object[]{0,false};
}
public int FileSize(StarObjectClass self,int Handle){
try{
InputStream dataSource = getAssets().open("index.html");
return dataSource.available();
}
catch(Exception e){
return 0;
}
}
public void FileClose(StarObjectClass self,int Handle){
return;
}
public int FileRead(StarObjectClass self,int Handle,StarBinBufClass Buf,int Size){
try{
InputStream dataSource = getAssets().open("index.html");
byte[] buffer = new byte[Size];
int result = dataSource.read(buffer);
Buf._Clear();
Buf._Write(0, buffer, result);
return result;
}
catch(Exception e){
Buf._Clear();
return 0;
}
}
public void ScriptInit(StarObjectClass self,String ScriptName){
if( ScriptName.equals("lua") ){
SrvGroup._InitRaw("lua", Service);
StarObjectClass lua = Service._ImportRawContext("lua", "", false, "");
lua._Set("HostObject", new SendSmsClass());
}
});
For the instance, we create five functions : “FileOpen”, “FileRead”, “FileSize”, “FileClose”, and “ScriptInit”.
In FileOpen function, we returns a file handle for other functions. Because index.html is in assets, we define a pseudo handle 1 for it.
For "FileRead" function, input parameter is Buf and Size. Type of Buf is StarBinBufClass, which is defined in starcore for binary buf. Size is the maximum size for each read operation. In the example, the web page is not copied to application directory. It exists in assets of the installation package. We directly call function “open” of asset manager to read the file content and call “_Write” method of “StarBinBufClass” to return the page to web server. The return value of “FileRead” function is the size of data in bytes.
"ScriptInit" will be call when the first script is executed in the web page. The input parameter is script name, which may be “lua” or “python”. In this function, we create an instance of SendSmsClass, and assign it to lua to be called by script.
e. SendSmsClass
The SendSmsClass is simple. It has one function SendSms with number and txt as input parameter.
class SendSmsClass{
public void SendSms(String number,String txt){
if( number == null || txt == null )
return;
SmsManager sms=SmsManager.getDefault();
sms.sendTextMessage(number, null, txt, null, null);
}
};
f. Create a timer to drive starcore
The last step is to create a timer and call SRPDispatch method of starcore.
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg)
{
while( starcore._SRPDispatch(false) == true );
}
};
timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask()
{
@Override
public void run()
{
Message message = handler.obtainMessage();
message.what = 1;
message.sendToTarget();
}
}, 0, 10);
5. Screenshot
About the sample
The sample uses some functions defined starcore. For details about these functions, please refer to the documentation of starcore. The code embeds lua in webpage. Furthermore we can also embed python in the web page. It is also simple for python can work on android too.