Przeglądaj źródła

Added WIP HttpRequest module.

Mark Sibly 8 lat temu
rodzic
commit
bda06adfd8

+ 54 - 0
bananas/httprequest/httprequest_test.monkey2

@@ -0,0 +1,54 @@
+
+Namespace myapp
+
+#Import "<std>"
+#Import "<mojo>"
+#Import "<httprequest>"
+
+Using std..
+Using mojo..
+Using httprequest..
+
+Class MyWindow Extends Window
+	
+	Field req:HttpRequest
+
+	Method New( title:String="HttpRequest demo",width:Int=640,height:Int=480,flags:WindowFlags=Null )
+
+		Super.New( title,width,height,flags )
+		
+		req=New HttpRequest( "GET","http://www.blitzbasic.com",Lambda()
+		
+			Print "Ready state changed to "+Int( req.ReadyState )
+			
+			If req.ReadyState=4 
+				Print "ReponseText="+req.ResponseText
+				Print "Status="+req.Status
+			Endif
+		
+		End )
+		
+		New Fiber( Lambda()
+		
+			req.Send()
+			
+		End )
+	End
+
+	Method OnRender( canvas:Canvas ) Override
+	
+		App.RequestRender()
+	
+		canvas.DrawText( "Hello World!",Width/2,Height/2,.5,.5 )
+	End
+	
+End
+
+Function Main()
+
+	New AppInstance
+	
+	New MyWindow
+	
+	App.Run()
+End

+ 8 - 0
modules/httprequest/httprequest.monkey2

@@ -0,0 +1,8 @@
+
+Namespace httprequest
+
+#If __TARGET__="android"
+
+#Import "httprequest_android"
+
+#Endif

+ 238 - 0
modules/httprequest/httprequest_android.monkey2

@@ -0,0 +1,238 @@
+
+Namespace httprequest
+
+#Import "<jni>"
+#Import "<std>"
+#Import "<mojo>"
+#Import "<sdl2>"
+
+#Import "native/Monkey2HttpRequest.java"
+#Import "native/httprequest.cpp"
+#Import "native/httprequest.h"
+
+Using jni..
+Using std..
+Using mojo..
+Using sdl2..
+
+Extern Private
+
+Global onReadyStateChanged:Void(jobject,Int)="bbHttpRequest::onReadyStateChanged"
+
+Global onResponseReceived:Void(jobject,String,Int,Int)="bbHttpRequest::onResponseReceived"
+
+private
+
+Function OnMainFiber( func:Void() )
+	
+	If Fiber.Current()=Fiber.Main() func() Else App.Idle+=func
+	
+End
+
+Public
+
+Enum ReadyState
+	
+	Unsent=0
+	Opened=1
+	HeadersReceived=2
+	Loading=3
+	Done=4
+	Error=5
+
+End
+
+Class HttpRequest
+	
+	Field ReadyStateChanged:Void()
+	
+	Method New()
+
+		Local env:=Android_JNI_GetEnv()
+		
+		Init( env )
+		
+		Local obj:=env.AllocObject( _class )
+		
+		_obj=env.NewGlobalRef( obj )
+		
+		Insert()
+	End
+	
+	Method New( req:String,url:String,readyStateChanged:Void()=Null )
+		Self.New()
+		
+		ReadyStateChanged=readyStateChanged
+		
+		Open( req,url )
+	End
+	
+	Property ReadyState:ReadyState()
+		
+		Return Cast<ReadyState>( _readyState )
+
+	End
+	
+	Property ResponseText:String()
+		
+		Return _response
+	End
+	
+	Property Status:Int()
+		
+		Return _status
+	End
+	
+	Method Discard()
+		
+		Remove()
+		
+		Local env:=Android_JNI_GetEnv()
+		
+		env.DeleteGlobalRef( _obj )
+		
+	End
+	
+	Method Open( req:String,url:String )
+		
+		OnMainFiber( Lambda()
+		
+			Local env:=Android_JNI_GetEnv()
+		
+			env.CallVoidMethod( _obj,_open,New Variant[]( req,url ) )
+		End )
+	End
+	
+	Method SetHeader( header:String,value:String )
+		
+		OnMainFiber( Lambda()
+
+			Local env:=Android_JNI_GetEnv()
+		
+			env.CallVoidMethod( _obj,_setHeader,New Variant[]( header,value ) )
+		End )
+	End
+	
+	Method Send()
+		
+		Send( "" )
+	End
+	
+	Method Send( text:String )
+		
+		OnMainFiber( Lambda()
+
+			Local env:=Android_JNI_GetEnv()
+		
+			env.CallVoidMethod( _obj,_send,New Variant[]( text ) )
+		
+		End )
+		
+	End
+	
+	Private
+	
+	Global _list:HttpRequest
+	
+	Field _succ:HttpRequest
+	Field _obj:jobject
+	Field _readyState:Int
+	Field _response:String
+	Field _status:int
+	
+	Method New( peer:jobject )
+		_obj=peer
+	End
+	
+	Method Insert()
+		_succ=_list
+		_list=Self
+	End
+	
+	Method Remove()
+		local inst:=_list,pred:HttpRequest=Null
+		While inst
+			If inst=Self
+				If pred
+					pred._succ=_succ
+				Else
+					_list=_succ
+				Endif
+				Return
+			Endif
+			pred=inst
+			inst=inst._succ
+		Wend
+	End
+	
+	Global _class:jclass
+	Global _open:jmethodID
+	Global _setHeader:jmethodID
+	Global _send:jmethodID
+	
+	Function OnReadyStateChanged( obj:jobject,state:Int )
+		
+		Local env:=Android_JNI_GetEnv()
+		
+		Local inst:=_list
+		
+		While inst
+			
+			If env.IsSameObject( obj,inst._obj )
+				
+				inst._readyState=state
+				
+				inst.ReadyStateChanged()
+				
+				Return
+			Endif
+			
+			inst=inst._succ
+		Wend
+		
+	End
+	
+	Function OnResponseReceived( obj:jobject,response:String,status:Int,state:Int )
+
+		Local env:=Android_JNI_GetEnv()
+		
+		Local inst:=_list
+		
+		While inst
+			
+			If env.IsSameObject( obj,inst._obj )
+				
+				inst._response=response
+				
+				inst._status=status
+				
+				inst._readyState=state
+				
+				inst.ReadyStateChanged()
+			
+			Endif
+
+			inst=inst._succ
+		wend
+	End
+	
+	Function Init( env:JNIEnv )
+		If _class Return
+	
+		_class=env.FindClass( "com/monkey2/lib/Monkey2HttpRequest" )
+		If Not _class RuntimeError( "Can't find com.monkey2.lib.Monkey2HttpRequest class" )
+		
+		_open=env.GetMethodID( _class,"open","(Ljava/lang/String;Ljava/lang/String;)V" )
+		
+		_setHeader=env.GetMethodID( _class,"setHeader","(Ljava/lang/String;Ljava/lang/String;)V" )
+	
+		_send=env.GetMethodID( _class,"send","(Ljava/lang/String;)V" )
+		
+		onReadyStateChanged=OnReadyStateChanged
+		
+		onResponseReceived=OnResponseReceived
+	End
+	
+End
+
+		

+ 8 - 0
modules/httprequest/module.json

@@ -0,0 +1,8 @@
+{
+	"module":"httprequest",
+	"about":"HttpRequest module",
+	"author":"Mark Sibly",
+	"version":"1.0.0",
+	"depends":["jni","std","sdl2","mojo"]
+}
+

+ 116 - 0
modules/httprequest/native/Monkey2HttpRequest.java

@@ -0,0 +1,116 @@
+
+package com.monkey2.lib;
+
+import android.util.Log;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+public class Monkey2HttpRequest{
+
+	private static final String TAG = "Monkey2HttpRequest";
+
+	HttpURLConnection connection;
+	
+	int readyState;
+	
+	boolean busy;
+
+    native void onNativeReadyStateChanged( int state );
+    
+    native void onNativeResponseReceived( String response,int status,int state );
+    
+    void setReadyState( int state ){
+    
+    	if( state==readyState ) return;
+    	
+    	onNativeReadyStateChanged( state );
+    	
+    	readyState=state;
+    }
+	
+	void open( String req,String url ){
+	
+		if( readyState!=0 ) return;
+		
+		try{
+		
+			URL turl=new URL( url );
+			connection=(HttpURLConnection)turl.openConnection();
+			connection.setRequestMethod( req );
+			
+			setReadyState( 1 );
+			
+		}catch( IOException ex ){
+		
+			setReadyState( 5 );
+		}		
+	}
+	
+	void setHeader( String name,String value ){
+	
+		if( readyState!=1 || busy ) return;
+	
+		connection.setRequestProperty( name,value );
+	}
+	
+	void send( final String text ){
+	
+		if( readyState!=1 || busy ) return;
+		
+		busy=true;
+		
+		new Thread( new Runnable() {
+
+			public void run() {
+
+				try {
+				
+					if( text!=null && text.length()!=0 ){
+			
+						byte[] bytes=text.getBytes( "UTF-8" );
+
+						connection.setDoOutput( true );
+						connection.setFixedLengthStreamingMode( bytes.length );
+				
+						OutputStream out=connection.getOutputStream();
+						out.write( bytes,0,bytes.length );
+						out.close();
+					}
+					
+					InputStream in=connection.getInputStream();
+					
+					setReadyState( 3 );
+
+					byte[] buf = new byte[4096];
+					ByteArrayOutputStream out=new ByteArrayOutputStream(1024);
+					for (; ; ) {
+						int n = in.read(buf);
+						if (n < 0) break;
+						out.write(buf, 0, n);
+					}
+					in.close();
+
+					String response=new String( out.toByteArray(),"UTF-8" );
+
+					int status=connection.getResponseCode();
+					
+					onNativeResponseReceived( response,status,4 );
+					
+					readyState=4;
+					
+				} catch ( IOException ex) {
+				
+					setReadyState( 5 );
+				}
+				
+				busy=false;
+			}
+			
+		} ).start();
+	}
+}

+ 90 - 0
modules/httprequest/native/httprequest.cpp

@@ -0,0 +1,90 @@
+
+#include "httprequest.h"
+
+#include "../../std/async/native/async.h"
+
+extern "C" JNIEnv *Android_JNI_GetEnv();	//SDL2
+
+namespace bbHttpRequest{
+
+	bbFunction<void( jobject,bbInt )> onReadyStateChanged;
+
+	bbFunction<void( jobject,bbString,bbInt,bbInt )> onResponseReceived;
+}
+
+namespace{
+
+	struct ReadyStateChangedEvent : public bbAsync::Event{
+		
+		jobject obj;
+		int state;
+		
+		ReadyStateChangedEvent( jobject obj,int state ):obj( obj ),state( state ){
+		}
+		
+		void dispatch(){
+		
+			bbHttpRequest::onReadyStateChanged( obj,state );
+			
+			JNIEnv *env=Android_JNI_GetEnv();
+			
+			env->DeleteGlobalRef( obj );
+			
+			delete this;
+		}
+	};
+
+	struct ResponseReceivedEvent : public bbAsync::Event{
+		
+		jobject obj;
+		jstring response;
+		int status;
+		int state;
+		
+		ResponseReceivedEvent( jobject obj,jstring response,int status,int state ):obj( obj ),response( response ),status( status ),state( state ){
+		}
+		
+		void dispatch(){
+		
+			JNIEnv *env=Android_JNI_GetEnv();
+			
+			const char *cstr=env->GetStringUTFChars( response,0 );
+		
+			bbString str=bbString::fromCString( cstr );
+		
+			env->ReleaseStringUTFChars( response,cstr );
+		
+			bbHttpRequest::onResponseReceived( obj,str,status,state );
+			
+			env->DeleteGlobalRef( response );
+			
+			env->DeleteGlobalRef( obj );
+			
+			delete this;
+		}
+	};
+}
+
+extern "C"{
+
+JNIEXPORT void JNICALL Java_com_monkey2_lib_Monkey2HttpRequest_onNativeReadyStateChanged( JNIEnv *env,jobject obj,int state ){
+
+	obj=env->NewGlobalRef( obj );
+
+	ReadyStateChangedEvent *ev=new ReadyStateChangedEvent( obj,state );
+	
+	ev->post();
+}
+
+JNIEXPORT void JNICALL Java_com_monkey2_lib_Monkey2HttpRequest_onNativeResponseReceived( JNIEnv *env,jobject obj,jstring response,int status,int state ){
+
+	obj=env->NewGlobalRef( obj );
+	
+	response=(jstring)env->NewGlobalRef( response );
+	
+	ResponseReceivedEvent *ev=new ResponseReceivedEvent( obj,response,status,state );
+	
+	ev->post();
+}
+
+}

+ 12 - 0
modules/httprequest/native/httprequest.h

@@ -0,0 +1,12 @@
+
+#include <bbmonkey.h>
+
+#include <jni.h>
+
+namespace bbHttpRequest{
+
+	extern bbFunction<void( jobject,bbInt )> onReadyStateChanged;
+	
+	extern bbFunction<void( jobject,bbString,bbInt,bbInt )> onResponseReceived;
+
+}