/*
* Copyright (C) 2012- Peer internet solutions & Finalist IT Group
*
* This file is part of mixare.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>
*/
package org.mixare.plugin;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.mixare.lib.marker.Marker;
import org.mixare.lib.service.IMarkerService;
import org.mixare.plugin.connection.ActivityConnection;
import org.mixare.plugin.connection.MarkerServiceConnection;
import org.mixare.plugin.remoteobjects.RemoteMarker;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.os.RemoteException;
/**
* Searches, loads and executes available plugins that are installed on the device.
* @author A.Egal
*/
public class PluginLoader {
private static PluginLoader instance;
private Activity activity;
private Map<String, PluginConnection> pluginMap = new HashMap<String, PluginConnection>();
private int pendingActivitiesOnResult = 0;
public static PluginLoader getInstance() {
if(instance == null){
instance = new PluginLoader();
}
return instance;
}
public void setActivity(Activity activity) {
this.activity = activity;
}
/**
* loads all plugins from a plugin type.
*/
public void loadPlugin(PluginType pluginType) {
PackageManager packageManager = activity.getPackageManager();
Intent baseIntent = new Intent(pluginType.getActionName());
baseIntent.setFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
List<ResolveInfo> list = packageManager.queryIntentServices(baseIntent,
PackageManager.GET_RESOLVED_FILTER);
initService(list, activity, pluginType);
}
/**
* Initializes the services from the loaded plugins and stores them in the pluginmap
*/
private void initService(List<ResolveInfo> list, Activity activity, PluginType pluginType){
for (int i = 0; i < list.size(); ++i) {
ResolveInfo info = list.get(i);
ServiceInfo sinfo = info.serviceInfo;
if (sinfo != null) {
Intent serviceIntent = new Intent();
serviceIntent.setClassName(sinfo.packageName, sinfo.name);
activity.startService(serviceIntent);
activity.bindService(serviceIntent, (ServiceConnection)pluginType.getPluginConnection(),
Context.BIND_AUTO_CREATE);
checkForPendingActivity(pluginType);
}
}
}
/**
* Unbinds all plugins from the activity
*/
public void unBindServices(){
for(PluginConnection pluginConnection : pluginMap.values()){
if(pluginConnection instanceof ServiceConnection){
activity.unbindService((ServiceConnection)pluginConnection);
}
}
}
/**
* Starts an activity plugin
*/
public void startPlugin(PluginType pluginType, String pluginName){
if(pluginType.getLoader() == Loader.Activity){
ActivityConnection activityConnection = (ActivityConnection)pluginMap.get(pluginName);
activityConnection.startActivityForResult(activity);
}
else{
throw new PluginNotFoundException("Cannot directly start a non-activity plugin," +
" you must call a instance for it");
}
}
protected void addFoundPluginToMap(String pluginName, PluginConnection pluginConnection){
pluginMap.put(pluginName, pluginConnection);
}
public Marker getMarkerInstance(String markername, int id, String title,
double latitude, double longitude, double altitude, String link,
int type, int color) throws PluginNotFoundException, RemoteException {
MarkerServiceConnection msc = (MarkerServiceConnection)pluginMap.get(PluginType.MARKER.toString());
IMarkerService iMarkerService = msc.getMarkerServices().get(markername);
if (iMarkerService == null) {
throw new PluginNotFoundException();
}
RemoteMarker rm = new RemoteMarker(iMarkerService);
rm.buildMarker(id, title, latitude, longitude, altitude, link, type, color);
return rm;
}
public PluginConnection getPluginConnection(String name){
return pluginMap.get(name);
}
public int getPendingActivitiesOnResult(){
return pendingActivitiesOnResult;
}
public void increasePendingActivitiesOnResult(){
pendingActivitiesOnResult++;
}
public void decreasePendingActivitiesOnResult(){
pendingActivitiesOnResult--;
}
private void checkForPendingActivity(PluginType pluginType){
if(pluginType.getLoader() == Loader.Activity){
increasePendingActivitiesOnResult();
}
}
}