Skip to content

Commit

Permalink
Merge pull request #269 from akvo/release/2.1.2
Browse files Browse the repository at this point in the history
Release/2.1.2
  • Loading branch information
ichinaski committed Feb 20, 2015
2 parents d9dd7b6 + 2f26d11 commit ba86892
Show file tree
Hide file tree
Showing 18 changed files with 269 additions and 155 deletions.
14 changes: 14 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
Akvo FLOW app release notes
===========================

#ver 2.1.2
Date: 20 February 2015

New and noteworthy
------------------
* Synchronised datapoints (monitoring surveys) can now get the media responses downloaded (images and videos) [#96]

Resolved issues
---------------
* Lack of GPS results no longer in an app crash [#262]
* Option values trailing spaces are now handled correctly. This caused some dependent questions to not be displayed [#261]
* Manual entries in geoshape features display a confirmation dialog [#236]
* Add `androidId` unique identifier to device attributes [#259]

#ver 2.1.1
Date: 28 January 2015

Expand Down
2 changes: 1 addition & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.akvo.flow"
android:versionCode="1"
android:versionName="2.1.1" >
android:versionName="2.1.2" >

<uses-sdk
android:minSdkVersion="10"
Expand Down
17 changes: 12 additions & 5 deletions app/src/main/java/org/akvo/flow/activity/GeoshapeActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -157,9 +157,6 @@ private void selectFeature(Feature feature, Marker marker) {
}

private void addPoint(LatLng point) {
if (mCurrentFeature == null) {
return;
}
mCurrentFeature.addPoint(point);
mClearPointBtn.setEnabled(true);
}
Expand Down Expand Up @@ -413,8 +410,18 @@ public void onMapClick(LatLng latLng) {
}

@Override
public void onMapLongClick(LatLng latLng) {
addPoint(latLng);
public void onMapLongClick(final LatLng latLng) {
if (mCurrentFeature == null) {
return;
}
ViewUtil.showConfirmDialog(R.string.add_point_title,
R.string.add_point_text, GeoshapeActivity.this, true,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
addPoint(latLng);
}
});
}

@Override
Expand Down
65 changes: 31 additions & 34 deletions app/src/main/java/org/akvo/flow/api/FlowApi.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2013 Stichting Akvo (Akvo Foundation)
* Copyright (C) 2013-2015 Stichting Akvo (Akvo Foundation)
*
* This file is part of Akvo FLOW.
*
Expand Down Expand Up @@ -43,37 +43,38 @@
import org.akvo.flow.exception.HttpException.Status;
import org.akvo.flow.util.ConstantUtil;
import org.akvo.flow.util.HttpUtil;
import org.akvo.flow.util.PlatformUtil;
import org.akvo.flow.util.PropertyUtil;
import org.akvo.flow.util.StatusUtil;

public class FlowApi {
private static final String TAG = FlowApi.class.getSimpleName();

private static final String BASE_URL;
private static final String API_KEY;
private static final String PHONE_NUMBER;
private static final String IMEI;
private static final String API_KEY;

static {
Context context = FlowApp.getApp();
BASE_URL = StatusUtil.getServerBase(context);
PHONE_NUMBER = getPhoneNumber(context);
IMEI = getImei(context);
API_KEY = getApiKey(context);
PHONE_NUMBER = StatusUtil.getPhoneNumber(context);
IMEI = StatusUtil.getImei(context);
}

public List<SurveyedLocale> getSurveyedLocales(long surveyGroup, String timestamp)
throws IOException, HttpException {
final String query = PARAM.IMEI + IMEI
+ "&" + PARAM.LAST_UPDATED + (!TextUtils.isEmpty(timestamp)? timestamp : "0")
+ "&" + PARAM.PHONE_NUMBER + PHONE_NUMBER
+ "&" + PARAM.SURVEY_GROUP + surveyGroup
+ "&" + PARAM.TIMESTAMP + getTimestamp();
final String query = Param.IMEI + IMEI
+ "&" + Param.LAST_UPDATED + (!TextUtils.isEmpty(timestamp)? timestamp : "0")
+ "&" + Param.PHONE_NUMBER + PHONE_NUMBER
+ "&" + Param.SURVEY_GROUP + surveyGroup
+ "&" + Param.TIMESTAMP + getTimestamp();

final String url = BASE_URL + Path.SURVEYED_LOCALE
+ "?" + query
//+ "&" + PARAM.HMAC + URLEncoder.encode(getAuthorization(query), "UTF-8");
+ "&" + PARAM.HMAC + getAuthorization(query);
+ "&" + Param.HMAC + getAuthorization(query);
String response = HttpUtil.httpGet(url);
if (response != null) {
SurveyedLocalesResponse slRes = new SurveyedLocaleParser().parseResponse(response);
Expand All @@ -86,32 +87,18 @@ public List<SurveyedLocale> getSurveyedLocales(long surveyGroup, String timestam
return null;
}

private static String getPhoneNumber(Context context) {
try {
String phoneNumber = StatusUtil.getPhoneNumber(context);
if (phoneNumber != null) {
return URLEncoder.encode(phoneNumber, "UTF-8");
}
private static String URLEncode(String param) {
if (TextUtils.isEmpty(param)) {
return "";
} catch (UnsupportedEncodingException e) {
Log.e(TAG, e.getMessage());
return null;
}
}

private static String getImei(Context context) {
try {
String imei = StatusUtil.getImei(context);
if (imei != null) {
return URLEncoder.encode(StatusUtil.getImei(context), "UTF-8");
}
return "";
return URLEncoder.encode(param, "UTF-8");
} catch (UnsupportedEncodingException e) {
Log.e(TAG, e.getMessage());
return null;
return "";
}
}

private static String getApiKey(Context context) {
PropertyUtil props = new PropertyUtil(context.getResources());
return props.getProperty(ConstantUtil.API_KEY);
Expand All @@ -128,9 +115,7 @@ private String getAuthorization(String query) {
byte[] rawHmac = mac.doFinal(query.getBytes());

authorization = Base64.encodeToString(rawHmac, Base64.DEFAULT);
} catch (NoSuchAlgorithmException e) {
Log.e(TAG, e.getMessage());
} catch (InvalidKeyException e) {
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
Log.e(TAG, e.getMessage());
}

Expand All @@ -149,17 +134,29 @@ private String getTimestamp() {
return null;
}
}

public static String getDeviceParams() {
Context context = FlowApp.getApp();
return Param.PHONE_NUMBER + URLEncode(StatusUtil.getPhoneNumber(context))
+ "&" + Param.ANDROID_ID + URLEncode(PlatformUtil.getAndroidID(context))
+ "&" + Param.IMEI + URLEncode(StatusUtil.getImei(context))
+ "&" + Param.VERSION + URLEncode(PlatformUtil.getVersionName(context))
+ "&" + Param.DEVICE_ID + URLEncode(StatusUtil.getDeviceId(context));
}

interface Path {
String SURVEYED_LOCALE = "/surveyedlocale";
}

interface PARAM {
interface Param {
String SURVEY_GROUP = "surveyGroupId=";
String PHONE_NUMBER = "phoneNumber=";
String IMEI = "imei=";
String TIMESTAMP = "ts=";
String LAST_UPDATED = "lastUpdateTime=";
String HMAC = "h=";
String VERSION = "ver=";
String DEVICE_ID = "devId=";
String ANDROID_ID = "androidId=";
}
}
83 changes: 83 additions & 0 deletions app/src/main/java/org/akvo/flow/async/MediaSyncTask.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* Copyright (C) 2015 Stichting Akvo (Akvo Foundation)
*
* This file is part of Akvo FLOW.
*
* Akvo FLOW is free software: you can redistribute it and modify it under the terms of
* the GNU Affero General Public License (AGPL) as published by the Free Software Foundation,
* either version 3 of the License or any later version.
*
* Akvo FLOW 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 Affero General Public License included below for more details.
*
* The full license text can also be seen at <http://www.gnu.org/licenses/agpl.html>.
*/

package org.akvo.flow.async;

import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;

import org.akvo.flow.api.S3Api;
import org.akvo.flow.util.ConstantUtil;
import org.akvo.flow.util.StatusUtil;

import java.io.File;
import java.io.IOException;
import java.lang.ref.WeakReference;

/**
* Download media files (images, videos) from synced forms.
*/
public class MediaSyncTask extends AsyncTask<Void, Void, Boolean> {
private static final String TAG = MediaSyncTask.class.getSimpleName();

public interface DownloadListener {
public void onResourceDownload(boolean done);
}

private WeakReference<DownloadListener> mListener;// Use a WeakReferences to avoid memory leaks
private Context mContext;
private File mFile;

/**
* Download a media file. Provided file must be already updated to use the local filesystem path.
*/
public MediaSyncTask(Context context, File file, DownloadListener listener) {
mContext = context.getApplicationContext();
mListener = new WeakReference<>(listener);
mFile = file;
}

@Override
protected Boolean doInBackground(Void... params) {
if (!StatusUtil.hasDataConnection(mContext)) {
Log.d(TAG, "No internet connection. Can't perform the requested operation");
return false;
}

try {
// Download resource and return success status
S3Api s3 = new S3Api(mContext);
s3.get(ConstantUtil.S3_IMAGE_DIR + mFile.getName(), mFile);
return true;
} catch (IOException e) {
Log.e(TAG, e.getMessage());
if (mFile.exists()) {
mFile.delete();
}
}
return false;
}

@Override
protected void onPostExecute(Boolean result) {
final DownloadListener listener = mListener.get();
if (listener != null) {
listener.onResourceDownload(Boolean.TRUE.equals(result));
}
}

}
4 changes: 2 additions & 2 deletions app/src/main/java/org/akvo/flow/domain/Dependency.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2010-2012 Stichting Akvo (Akvo Foundation)
* Copyright (C) 2010-2015 Stichting Akvo (Akvo Foundation)
*
* This file is part of Akvo FLOW.
*
Expand Down Expand Up @@ -52,7 +52,7 @@ public boolean isMatch(String val) {

for (String v : val.split("\\|", -1)) {
for (String a : answer.split("\\|", -1)) {
if (v.equals(a)) {
if (v.trim().equals(a.trim())) {
return true;
}
}
Expand Down
Loading

0 comments on commit ba86892

Please sign in to comment.