org.odk.collect.android.application.Collect.java Source code

Java tutorial

Introduction

Here is the source code for org.odk.collect.android.application.Collect.java

Source

/*
 * Copyright (C) 2011 University of Washington
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */

package org.odk.collect.android.application;

import android.app.Application;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.database.Cursor;
import android.net.Uri;
import android.os.Environment;
import android.preference.PreferenceManager;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import android.widget.Toast;

import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.microsoft.windowsazure.mobileservices.MobileServiceClient;
import com.microsoft.windowsazure.mobileservices.ServiceFilterResponse;
import com.microsoft.windowsazure.mobileservices.TableJsonQueryCallback;

import org.odk.collect.android.R;
import org.odk.collect.android.database.ActivityLogger;
import org.odk.collect.android.external.ExternalDataManager;
import org.odk.collect.android.logic.FormController;
import org.odk.collect.android.logic.PropertyManager;
import org.odk.collect.android.preferences.PreferencesActivity;
import org.odk.collect.android.provider.FormsProviderAPI;
import org.odk.collect.android.utilities.AgingCredentialsProvider;
import org.opendatakit.httpclientandroidlib.client.CookieStore;
import org.opendatakit.httpclientandroidlib.client.CredentialsProvider;
import org.opendatakit.httpclientandroidlib.client.protocol.ClientContext;
import org.opendatakit.httpclientandroidlib.impl.client.BasicCookieStore;
import org.opendatakit.httpclientandroidlib.protocol.BasicHttpContext;
import org.opendatakit.httpclientandroidlib.protocol.HttpContext;

import java.io.File;
import java.net.MalformedURLException;
import java.util.concurrent.CountDownLatch;

/**
 * Extends the Application class to implement
 *
 * @author carlhartung
 */
public class Collect extends Application {

    // Storage paths
    public static final String ODK_ROOT = Environment.getExternalStorageDirectory() + File.separator + "odk";
    public static final String FORMS_PATH = ODK_ROOT + File.separator + "forms";
    public static final String INSTANCES_PATH = ODK_ROOT + File.separator + "instances";
    public static final String CACHE_PATH = ODK_ROOT + File.separator + ".cache";
    public static final String METADATA_PATH = ODK_ROOT + File.separator + "metadata";
    public static final String TMPFILE_PATH = CACHE_PATH + File.separator + "tmp.jpg";
    public static final String TMPDRAWFILE_PATH = CACHE_PATH + File.separator + "tmpDraw.jpg";
    public static final String TMPXML_PATH = CACHE_PATH + File.separator + "tmp.xml";
    public static final String LOG_PATH = ODK_ROOT + File.separator + "log";

    public static final String DEFAULT_FONTSIZE = "21";

    // share all session cookies across all sessions...
    private CookieStore cookieStore = new BasicCookieStore();
    // retain credentials for 7 minutes...
    private CredentialsProvider credsProvider = new AgingCredentialsProvider(7 * 60 * 1000);
    private ActivityLogger mActivityLogger;
    private FormController mFormController = null;
    private ExternalDataManager externalDataManager;

    private static Collect singleton = null;

    public static Collect getInstance() {
        return singleton;
    }

    public ActivityLogger getActivityLogger() {
        return mActivityLogger;
    }

    public FormController getFormController() {
        return mFormController;
    }

    public void setFormController(FormController controller) {
        mFormController = controller;
    }

    public ExternalDataManager getExternalDataManager() {
        return externalDataManager;
    }

    public void setExternalDataManager(ExternalDataManager externalDataManager) {
        this.externalDataManager = externalDataManager;
    }

    public static int getQuestionFontsize() {
        SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(Collect.getInstance());
        String question_font = settings.getString(PreferencesActivity.KEY_FONT_SIZE, Collect.DEFAULT_FONTSIZE);
        int questionFontsize = Integer.valueOf(question_font);
        return questionFontsize;
    }

    public String getVersionedAppName() {
        String versionDetail = "";
        try {
            PackageInfo pinfo;
            pinfo = getPackageManager().getPackageInfo(getPackageName(), 0);
            int versionNumber = pinfo.versionCode;
            String versionName = pinfo.versionName;
            versionDetail = " " + versionName + " (" + versionNumber + ")";
        } catch (NameNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return getString(R.string.app_name) + versionDetail;
    }

    /**
     * Creates required directories on the SDCard (or other external storage)
     *
     * @throws RuntimeException if there is no SDCard or the directory exists as a non directory
     */
    public static void createODKDirs() throws RuntimeException {
        String cardstatus = Environment.getExternalStorageState();
        if (!cardstatus.equals(Environment.MEDIA_MOUNTED)) {
            throw new RuntimeException(Collect.getInstance().getString(R.string.sdcard_unmounted, cardstatus));
        }

        String[] dirs = { ODK_ROOT, FORMS_PATH, INSTANCES_PATH, CACHE_PATH, METADATA_PATH };

        for (String dirName : dirs) {
            File dir = new File(dirName);
            if (!dir.exists()) {
                if (!dir.mkdirs()) {
                    RuntimeException e = new RuntimeException("ODK reports :: Cannot create directory: " + dirName);
                    throw e;
                }
            } else {
                if (!dir.isDirectory()) {
                    RuntimeException e = new RuntimeException(
                            "ODK reports :: " + dirName + " exists, but is not a directory");
                    throw e;
                }
            }
        }
    }

    /**
     * Predicate that tests whether a directory path might refer to an
     * ODK Tables instance data directory (e.g., for media attachments).
     *
     * @param directory
     * @return
     */
    public static boolean isODKTablesInstanceDataDirectory(File directory) {
        /**
         * Special check to prevent deletion of files that
         * could be in use by ODK Tables.
         */
        String dirPath = directory.getAbsolutePath();
        if (dirPath.startsWith(Collect.ODK_ROOT)) {
            dirPath = dirPath.substring(Collect.ODK_ROOT.length());
            String[] parts = dirPath.split(File.separator);
            // [appName, instances, tableId, instanceId ]
            if (parts.length == 4 && parts[1].equals("instances")) {
                return true;
            }
        }
        return false;
    }

    /**
     * Construct and return a session context with shared cookieStore and credsProvider so a user
     * does not have to re-enter login information.
     *
     * @return
     */
    public synchronized HttpContext getHttpContext() {

        // context holds authentication state machine, so it cannot be
        // shared across independent activities.
        HttpContext localContext = new BasicHttpContext();

        localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
        localContext.setAttribute(ClientContext.CREDS_PROVIDER, credsProvider);

        return localContext;
    }

    public CredentialsProvider getCredentialsProvider() {
        return credsProvider;
    }

    public CookieStore getCookieStore() {
        return cookieStore;
    }

    @Override
    public void onCreate() {
        singleton = this;

        // // set up logging defaults for apache http component stack
        // Log log;
        // log = LogFactory.getLog("org.opendatakit.httpclientandroidlib");
        // log.enableError(true);
        // log.enableWarn(true);
        // log.enableInfo(true);
        // log.enableDebug(true);
        // log = LogFactory.getLog("org.opendatakit.httpclientandroidlib.wire");
        // log.enableError(true);
        // log.enableWarn(false);
        // log.enableInfo(false);
        // log.enableDebug(false);

        PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
        super.onCreate();

        PropertyManager mgr = new PropertyManager(this);
        mActivityLogger = new ActivityLogger(mgr.getSingularProperty(PropertyManager.DEVICE_ID_PROPERTY));

    }

    /* START FLIKK ADDITIONS */
    public static final String SurveysUpdatedKey = "net.flikk.surveysupdated";
    public JsonArray Surveys;
    public static Context Ctx; //for unit testing

    public void beginGetSurveys(Context ctx) {
        Ctx = ctx;

        try {
            MobileServiceClient client = new MobileServiceClient("https://flikkodk.azure-mobile.net/",
                    "SenCBSjDhFGTRqbwhDMiKKZJSxBhGK39", Ctx);

            PropertyManager manager = new PropertyManager(this);
            String userName = manager.getSingularProperty("username");
            String userNameSpaced = userName.replace('_', ' ');

            client.getTable("Survey").where().field("Completed").eq(false).and().field("surveyorname")
                    .eq(userNameSpaced).execute(new TableJsonQueryCallback() {
                        @Override
                        public void onCompleted(JsonElement result, int count, Exception exception,
                                ServiceFilterResponse response) {
                            if (exception == null) {
                                Log.d("Azure", result.toString());
                                JsonArray res = (JsonArray) result;
                                Surveys = new JsonArray();
                                for (JsonElement e : res) {
                                    try {
                                        JsonObject o = (JsonObject) e;
                                        if (e != null) {
                                            JsonElement address1 = o.get("address1");
                                            if (address1.isJsonNull()) {
                                            } else if (address1.getAsString().length() == 0) {
                                            } else {
                                                Surveys.add(e);
                                            }
                                        }
                                    } catch (Exception ex) {
                                    }
                                }
                                sendBroadcast(SurveysUpdatedKey);
                            } else {
                                Log.wtf("Azure", exception.getMessage());
                                //receivedMessage = exception.getMessage();
                            }
                        }
                    });

        } catch (MalformedURLException e) {

        }

    }

    public void sendBroadcast(String key) {
        //must be R.string.activities_updated or...
        Intent intent = new Intent(key);
        LocalBroadcastManager.getInstance(Ctx).sendBroadcast(intent);
    }

    public String getBlankFormPath(String surveyType) {
        Cursor c = null;
        String mFormPath = null;
        Uri mFormUri = null;
        Uri uri = FormsProviderAPI.FormsColumns.CONTENT_URI;
        //"content://org.odk.collect.android.provider.odk.forms/forms");
        try {
            ContentResolver cr = getContentResolver();
            //ContentResolver.query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String)()
            String queryString = String.format("displayName like '%s%%'", surveyType);
            c = cr.query(uri, null, //selection columns
                    queryString, null, //sort columns
                    null);

            c.moveToFirst();
            int i;
            /*for(i = 0; i<c.getColumnCount(); ++i){
            Log.d("flikk",String.format("%s",c.getColumnName(i)));
            }
            Log.d("flikk",String.format("Found %d forms", c.getCount()));
            */

            mFormPath = c.getString(c.getColumnIndex(FormsProviderAPI.FormsColumns.FORM_FILE_PATH));
            mFormUri = ContentUris.withAppendedId(FormsProviderAPI.FormsColumns.CONTENT_URI,
                    c.getInt(c.getColumnIndex(FormsProviderAPI.FormsColumns._ID)));
            Log.d("flikk", mFormPath);
            while (c.moveToNext()) {
                mFormPath = c.getString(c.getColumnIndex(FormsProviderAPI.FormsColumns.FORM_FILE_PATH));
                mFormUri = ContentUris.withAppendedId(FormsProviderAPI.FormsColumns.CONTENT_URI,
                        c.getInt(c.getColumnIndex(FormsProviderAPI.FormsColumns._ID)));
                Log.d("flikk", mFormPath);
            }

        } catch (Exception ex) {
        }

        //Log.d("flikk",String.format("selected form is %s", mFormPath ));
        //needs to look like content://org.odk.collect.android.provider.odk.forms/forms/3

        mFormPath = "content:/" + mFormPath;

        //return mFormPath;
        return mFormUri.toString();
    }

    public Intent getStartSurveyIntent(int surveyIndex) {
        //get the item we are on
        JsonObject o = (JsonObject) Surveys.get(surveyIndex);
        if (o != null) {
            StringBuilder sb = new StringBuilder();
            JsonElement surveyTypeCode = o.get("SurveyTypeCode");
            JsonElement address1 = o.get("address1");
            JsonElement address2 = o.get("address2");
            JsonElement surveynumber = o.get("surveynumber");
            if (surveyTypeCode.isJsonNull() || surveyTypeCode.getAsString().length() == 0)
                sb.append("No Survey Type ");
            String address = "";
            if (!address1.isJsonNull() && address1.getAsString().length() > 0) {
                address += address1.getAsString();
            }
            if (!address2.isJsonNull() && address2.getAsString().length() > 0) {
                address += address2.getAsString();
            }
            if (address.length() == 0)
                sb.append("No Address ");
            if (surveynumber.isJsonNull() || surveynumber.getAsString().length() == 0)
                sb.append("No Survey Number Type");

            if (sb.length() > 0) {
                Toast toast = Toast.makeText(this, sb.toString(), Toast.LENGTH_LONG);
                return null;
            }

            String mFormPath = getBlankFormPath(surveyTypeCode.getAsString());

            if (mFormPath == null) {
                Toast toast = Toast.makeText(this,
                        String.format("Could not find a Form for %s. Please Download Blank Forms.",
                                surveyTypeCode.getAsString()),
                        Toast.LENGTH_LONG);
                return null;
            }

            //find the uri of the form in the SQLLite database
            Uri formUri = Uri.parse(mFormPath);
            Intent intent = new Intent(Intent.ACTION_EDIT, formUri);
            intent.putExtra("flikk", o.toString());
            //intent.setDataAndType(Uri.parse("vnd.android.cursor.item/vnd.odk.form"), mFormPath);

            //new Intent(ACTION_EDIT,
            //        Uri.parse(FormsProviderAPI.FormsColumns.FLIKK_SURVEY_TYPE))
            //startActivity(intent);

            return intent;

        }

        return null;
    }

    /* END FLIKK ADDITIONS */
}