Java tutorial
/* * 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 */ }