package mobi.monaca.framework;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import mobi.monaca.framework.bootloader.LocalFileBootloader;
import mobi.monaca.framework.nativeui.UIContext;
import mobi.monaca.framework.nativeui.component.SpinnerDialog;
import mobi.monaca.framework.nativeui.menu.MenuRepresentation;
import mobi.monaca.framework.nativeui.menu.MenuRepresentationBuilder;
import mobi.monaca.framework.psedo.GCMIntentService;
import mobi.monaca.framework.task.GCMRegistrationIdSenderTask;
import mobi.monaca.framework.util.MyLog;
import mobi.monaca.utils.MonacaConst;
import mobi.monaca.utils.MonacaDevice;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.annotation.TargetApi;
import android.app.Application;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.DialogInterface.OnDismissListener;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.webkit.CookieManager;
import android.webkit.CookieSyncManager;
/** This class manage the application's global state and variable. */
public class MonacaApplication extends Application {
private static final String TAG = MonacaApplication.class.getSimpleName();
protected static List<MonacaPageActivity> pages = null;
protected static Map<String, MenuRepresentation> menuMap = null;
private SpinnerDialog monacaSpinnerDialog;
protected static InternalSettings settings = null;
protected AppJsonSetting appJsonSetting;
/**
* if this is false, this app never use bootloader in any cases
*/
protected boolean enablesBootloader = true;
private BroadcastReceiver registeredReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String regId = intent.getStringExtra(GCMIntentService.KEY_REGID);
sendGCMRegisterIdToAppAPI(regId);
unregisterReceiver(this);
}
};
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1)
@Override
public void onCreate() {
MyLog.i(TAG, "onCreate()");
if (Build.VERSION.SDK_INT >= 12) {
CookieManager.setAcceptFileSchemeCookies(true);
}
CookieSyncManager.createInstance(this);
super.onCreate();
registerReceiver(registeredReceiver, new IntentFilter(GCMIntentService.ACTION_GCM_REGISTERED));
createMenuMap();
}
public void loadAppJsonSetting() {
JSONObject appJson = null;
try {
InputStream stream = getResources().getAssets().open("app.json");
byte[] buffer = new byte[stream.available()];
stream.read(buffer);
appJson = new JSONObject(new String(buffer, "UTF-8"));
} catch (IOException e) {
MyLog.e(TAG, e.getMessage());
} catch (JSONException e) {
MyLog.e(TAG, e.getMessage());
} catch (IllegalArgumentException e) {
MyLog.e(TAG, e.getMessage());
}catch (NullPointerException e) {
e.printStackTrace();
}
if (appJson == null) {
appJson = new JSONObject();
}
appJsonSetting = new AppJsonSetting(appJson);
boolean disableCookie = appJsonSetting.getDisableCookie();
CookieManager.getInstance().setAcceptCookie(!disableCookie);
if (!disableCookie) {
CookieSyncManager.getInstance().startSync();
String assetUrl = appJsonSetting.shouldExtractAssets() || needToUseBootloader() ? "file:///data/" : "file:///android_asset/www/";
//MyLog.d(TAG, projectUrl);
CookieManager.getInstance().setCookie(assetUrl, "MONACA_CLOUD_DEVICE_ID=" + MonacaDevice.getDeviceId(this));
CookieSyncManager.getInstance().sync();
CookieManager.getInstance().setCookie(assetUrl, "Domain=" + appJsonSetting.getMonacaCloudDomain());
CookieSyncManager.getInstance().sync();
CookieManager.getInstance().setCookie(assetUrl, "path=" + appJsonSetting.getMonacaCloudPath());
CookieSyncManager.getInstance().sync();
CookieManager.getInstance().setCookie(assetUrl, "secure");
CookieSyncManager.getInstance().sync();
}
}
public AppJsonSetting getAppJsonSetting() {
if (appJsonSetting == null) {
loadAppJsonSetting();
}
return appJsonSetting;
}
protected void createMenuMap() {
menuMap = new MenuRepresentationBuilder(getApplicationContext()).buildFromAssets(this, "www/app.menu");
}
public void showMonacaSpinnerDialog(UIContext uiContext, JSONArray args) throws Exception {
// dismiss old one if any
if (monacaSpinnerDialog != null && monacaSpinnerDialog.isShowing()) {
monacaSpinnerDialog.dismiss();
}
try {
monacaSpinnerDialog = new SpinnerDialog(uiContext, args);
monacaSpinnerDialog.setCancelable(true);
monacaSpinnerDialog.setOnDismissListener(new OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
// this causes duplication of dialog
// if (monacaSpinnerDialog != null) {
// monacaSpinnerDialog = null;
// }
}
});
monacaSpinnerDialog.setOnCancelListener(new OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
if (monacaSpinnerDialog != null) {
monacaSpinnerDialog = null;
}
}
});
monacaSpinnerDialog.show();
} catch (Exception e) {
Log.e("MONACA", e.getMessage());
throw e;
}
}
public void dismissMonacaSpinnerDialog() {
if (monacaSpinnerDialog != null) {
if (monacaSpinnerDialog.isShowing()) {
monacaSpinnerDialog.dismiss();
}
monacaSpinnerDialog = null;
}
}
public void hideMonacaSpinnerDialog(){
if (monacaSpinnerDialog != null && monacaSpinnerDialog.isShowing()) {
monacaSpinnerDialog.hide();
}
}
public void showMonacaSpinnerDialogIfAny(){
if (monacaSpinnerDialog != null) {
monacaSpinnerDialog.show();
}
}
public void updateSpinnerTitle(String title) {
if (monacaSpinnerDialog != null && monacaSpinnerDialog.isShowing()) {
monacaSpinnerDialog.updateTitleText(title);
}
}
public boolean allowAccess(String url) {
if (url.startsWith("file://")) {
Context context = this.getApplicationContext();
try {
url = new URI(url).normalize().toString();
} catch (Exception e) {
MyLog.e(TAG, e.getMessage());
return false;
}
if (url.startsWith("file:///android_asset/")) {
return true;
}
if (url.startsWith("file://" + context.getApplicationInfo().dataDir)) {
return !url.startsWith("file://" + context.getApplicationInfo().dataDir + "/shared_prefs/");
}
// allow access to SD card (some app need access to photos in SD
// card)
if (url.startsWith("file:///mnt/")) {
return true;
}
if (url.startsWith("file://" + Environment.getExternalStorageDirectory().getPath())) {
return true;
}
return false;
}
return true;
}
/** Add a MonacaPageActivity instance to the page list. */
public static void addPage(MonacaPageActivity page) {
if (pages == null) {
pages = new ArrayList<MonacaPageActivity>();
}
pages.add(page);
}
/** Remove a MonacaPageActivity instance from the page list. */
public static void removePage(MonacaPageActivity page) {
if (pages != null) {
pages.remove(page);
}
}
/** Get either MenuRepresentation or null from menu name. */
public static MenuRepresentation findMenuRepresentation(String name) {
if (menuMap != null) {
return menuMap.containsKey(name) ? menuMap.get(name) : menuMap.get("default");
}
return null;
}
/** Get all MonacaPageActivity instances in this application. */
public static List<MonacaPageActivity> getPages() {
return pages != null ? pages : new ArrayList<MonacaPageActivity>();
}
/** Get Monaca's internal settings object */
public InternalSettings getInternalSettings() {
if (settings == null) {
try {
settings = new InternalSettings(this.getPackageManager().getApplicationInfo(this.getPackageName(), PackageManager.GET_META_DATA).metaData);
} catch (Exception e) {
MyLog.d(this.getClass().getSimpleName(), "InternalSettings initialization fail", e);
settings = new InternalSettings(new Bundle());
}
}
return settings;
}
@Override
public void onTerminate() {
MyLog.i(TAG, "onTerminate()");
pages = null;
menuMap = null;
super.onTerminate();
}
public String getPushProjectId() {
return getAppJsonSetting().getPushProjectId();
}
public void sendGCMRegisterIdToAppAPI(String regId) {
new GCMRegistrationIdSenderTask(this, MonacaConst.getPushRegistrationAPIUrl(this, getPushProjectId()), regId) {
@Override
protected void onSucceededRegistration(JSONObject resultJson) {
}
@Override
protected void onFailedRegistration(JSONObject resultJson) {
}
@Override
protected void onClosedTask() {
}
}.execute();
}
public boolean enablesBootloader() {
return enablesBootloader;
}
/**
* should this app use bootloader when initializing
* @return
*/
public boolean needToUseBootloader() {
return enablesBootloader && LocalFileBootloader.needToUseLocalFileBootloader();
}
}