Friendiqa/source-android/androidnative.pri/java/src/androidnative/SystemDispatcher.java

256 lines
7.4 KiB
Java

// Author: Ben Lau (https://github.com/benlau)
package androidnative;
import android.app.Activity;
import org.qtproject.qt5.android.QtNative;
import java.lang.String;
import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.ArrayList;
import java.util.Queue;
import java.util.LinkedList;
import java.lang.ClassLoader;
import java.lang.reflect.Method;
import java.lang.Thread;
import android.util.Log;
import android.os.Handler;
import android.os.Looper;
import android.content.Intent;
//import android.content.*;
//import android.app.*;
import android.os.*;
import java.util.concurrent.Semaphore;
import java.io.StringWriter;
import java.io.PrintWriter;
public class SystemDispatcher {
public interface Listener {
/** Every messages posted on SystemMessenger will trigger this function.
@return true if the message is handled. Otherwise, it should be false.
*/
public void onDispatched(String type , Map message);
}
/**
@threadsafe
@remarks: The function may not be running from the UI thread. It is listener's duty to handle multiple threading issue.
*/
public static void dispatch(String name) {
dispatch(name,null);
}
/** Dispatch a message.
@threadsafe
@remarks: The function may not be running from the UI thread. It is listener's duty to handle multiple threading issue.
*/
public static void dispatch(String type,Map message) {
try {
Payload payload;
mutex.acquire();
if (dispatching) {
payload = new Payload();
payload.type = type;
payload.message = message;
queue.add(payload);
mutex.release();
return;
}
dispatching = true;
mutex.release();
emit(type,message); // Emit
mutex.acquire(); // Process queued message
while (queue.size() > 0 ) {
payload = queue.poll();
mutex.release();
emit(payload.type,payload.message);
mutex.acquire();
}
dispatching = false;
mutex.release();
} catch (Exception e) {
Log.e(TAG,"exception",e);
}
}
public static void addListener(Listener listener ) {
try {
mutex.acquire();
listeners.add(listener);
mutex.release();
} catch (Exception e) {
Log.e(TAG,"exception",e);
}
}
public static void removeListener(Listener listener ) {
try {
mutex.acquire();
listeners.remove(listener);
mutex.release();
} catch (Exception e) {
Log.e(TAG,"exception",e);
}
}
public static String ACTIVITY_RESUME_MESSAGE = "androidnative.Activity.onResume";
public static String ACTIVITY_RESULT_MESSAGE = "androidnative.Activity.onActivityResult";
public static String SYSTEM_DISPATCHER_LOAD_CLASS_MESSAGE = "androidnative.SystemDispatcher.loadClass";
public static String SYSTEM_DISPATCHER_SET_INITIALIZED_MESSAGE = "androidnative.SystemDispatcher.setInitialized";
public static boolean isIntentPending=false;
public static boolean isInitialized=false;
private static Map waitingIntent;
/** A helper function to dispatch a massage when onResume is invoked in the Activity class
*/
public static void onActivityResume() {
dispatch(ACTIVITY_RESUME_MESSAGE);
}
/** A helper function to dispatch a message based on the input argument fron Activity.onActivityResult
*/
public static void onActivityResult (int requestCode, int resultCode, Intent data) {
Map message = new HashMap();
message.put("requestCode",requestCode);
message.put("resultCode",resultCode);
message.put("data",data);
if(isInitialized) {
dispatch(ACTIVITY_RESULT_MESSAGE,message);
waitingIntent=null;
isIntentPending=false;
} else { //onIntent start
waitingIntent = message;
isIntentPending = true;
}
//onIntent end
}
private static class Payload {
public String type;
public Map message;
}
private static String TAG = "AndroidNative";
private static final Semaphore mutex = new Semaphore(1);
private static Queue<Payload> queue = new LinkedList();
private static List<Listener> listeners = new ArrayList<Listener>();
private static boolean dispatching = false;
private static native void jniEmit(String name,Map message);
/** Emit onDispatched signal to registered listenter
*/
private static void emit(String name,Map message) {
for (int i = 0 ; i < listeners.size() ; i++ ) {
Listener listener = listeners.get(i);
try {
listener.onDispatched(name,message);
} catch (Exception e) {
Log.d(TAG, Log.getStackTraceString(e));
}
}
jniEmit(name,message);
}
private static void printMap(Map data) {
if (data == null)
return;
try {
for (Map.Entry entry : (Set<Map.Entry>) data.entrySet()) {
String key = (String) entry.getKey();
Object value = entry.getValue();
if (value == null)
continue;
if (value instanceof String) {
String stringValue = (String) value;
Log.d(TAG,String.format("%s : %s",key,stringValue));
} else if (value instanceof Integer) {
int intValue = (Integer) value;
Log.d(TAG,String.format("%s : %d",key,intValue));
} else if (value instanceof Boolean) {
Boolean booleanValue = (Boolean) value;
Log.d(TAG,String.format("%s : %b",key,booleanValue));
} else {
Log.d(TAG,String.format("%s : Non-supported data type[%s] is passed",key,value.getClass().getName()));
}
}
} catch (Exception e) {
Log.d(TAG,e.getMessage());
}
}
public static void loadClass(String className) {
try {
ClassLoader classLoader = SystemDispatcher.class.getClassLoader();
Class aClass = Class.forName(className,true,classLoader);
// Log.d(TAG,"Class Loaded: " + className);
} catch (ClassNotFoundException e) {
Log.e(TAG,"Failed to load class: " + className);
e.printStackTrace();
}
}
public static void setInitialized() {
isInitialized = true;
if(isIntentPending) {
isIntentPending = false;
dispatch(ACTIVITY_RESULT_MESSAGE,waitingIntent);
}
}
public static void init() {
SystemDispatcher.addListener(new SystemDispatcher.Listener() {
public void onDispatched(String type , Map message) {
// Log.d(TAG,String.format("%s %b",type ,type.equals(SYSTEM_DISPATCHER_LOAD_CLASS_MESSAGE)));
if (type.equals(SYSTEM_DISPATCHER_LOAD_CLASS_MESSAGE)) {
String className = (String) message.get("className");
loadClass(className);
}
if (type.equals(SYSTEM_DISPATCHER_SET_INITIALIZED_MESSAGE)) {
setInitialized();
}
}
});
}
}