Skip to content

Commit

Permalink
ManageDroneModelsAndAPIKeyActivity add API Key status indicator for #149
Browse files Browse the repository at this point in the history
  • Loading branch information
mkrupczak3 committed Jul 9, 2024
1 parent e98f81e commit 8c50150
Show file tree
Hide file tree
Showing 5 changed files with 173 additions and 17 deletions.
24 changes: 24 additions & 0 deletions app/src/main/java/com/openathena/AthenaActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
import android.widget.SeekBar;
import android.widget.TextView;

import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.io.FileDescriptor;
import java.io.IOException;
Expand Down Expand Up @@ -391,7 +393,29 @@ public int[] getImageDimensionsFromUri(Uri imageUri) {
// return cy;
// }

protected String getDemApiKey() {
String apiKey = "";
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
apiKey = sharedPreferences.getString("OPENTOPOGRAPHY_API_KEY", "");
if (apiKey.isEmpty()) {
apiKey = BuildConfig.OPENTOPOGRAPHY_API_KEY;
}
return apiKey;
}

protected boolean putDemApiKey(String newApiKey) {
// input validity checks
if (newApiKey == null || newApiKey.trim().isEmpty()) return false;
newApiKey = newApiKey.trim();
if (newApiKey.length() != 32) return false;
if (!StringUtils.isAlphanumeric(newApiKey)) return false;

SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.Editor prefsEditor = sharedPreferences.edit();
prefsEditor.putString("OPENTOPOGRAPHY_API_KEY", newApiKey);
prefsEditor.apply();
return true;
}

public void restorePrefs() {
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
Expand Down
54 changes: 45 additions & 9 deletions app/src/main/java/com/openathena/DemDownloader.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@

package com.openathena;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.util.Log;

import java.io.File;
import java.net.HttpURLConnection;
import java.net.URL;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.IOException;
import java.io.FileOutputStream;
Expand All @@ -26,14 +27,13 @@ public class DemDownloader
// add your API key to local.properties in root of the android project
// for example:
// OPENTOPOGRAPHY_API_KEY=hexnumbers
private String OPENTOPOGRAPHY_API_KEY = BuildConfig.OPENTOPOGRAPHY_API_KEY;
public static String TAG = DemDownloader.class.getSimpleName();
private static final String URL_STR = "https://portal.opentopography.org/API/globaldem?";
private int responseCode;
private int responseBytes;
private double s, w, n, e; // Bounding box coordinates
private String filenameSuffix = ".tiff";
private String outputFormatStr = "GTiff";
private static final String OUTPUT_FORMAT_STRING = "GTiff";
private Context context;

protected File demDir;
Expand All @@ -54,6 +54,40 @@ public DemDownloader(Context appContext, double lat, double lon, double length)
Log.d(TAG,"DemDownloader: "+n+","+s+","+e+","+w);
}

protected String getDemApiKey() {
if (context == null) return "";
String apiKey = "";
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
apiKey = sharedPreferences.getString("OPENTOPOGRAPHY_API_KEY", "");
if (apiKey.isEmpty()) {
apiKey = BuildConfig.OPENTOPOGRAPHY_API_KEY;
}
return apiKey;
}

// Method to check the validity of the API Key
public boolean isApiKeyValid() throws IOException {
// Minimal bounding box at a location with likely no data
String testUrl = URL_STR +
"demtype=SRTMGL1" +
"&south=0" +
"&north=0.01" +
"&west=0" +
"&east=0.01" +
"&outputFormat=" + OUTPUT_FORMAT_STRING +
"&API_Key=" + getDemApiKey();

URL url = new URL(testUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");

responseCode = connection.getResponseCode();
connection.disconnect();

// Check for valid responses indicating a valid API key
return (responseCode == HttpURLConnection.HTTP_OK || responseCode == HttpURLConnection.HTTP_NO_CONTENT || responseCode == HttpURLConnection.HTTP_BAD_REQUEST);
}

// Blocking download of a DEM from OpenTopography
public boolean syncDownload() throws IOException {
String demTypeStr;
Expand All @@ -75,9 +109,9 @@ public boolean syncDownload() throws IOException {
"&north=" + n +
"&west=" + w +
"&east=" + e +
"&outputFormat=" + outputFormatStr +
"&API_Key=" + OPENTOPOGRAPHY_API_KEY;
boolean b = false;
"&outputFormat=" + OUTPUT_FORMAT_STRING +
"&API_Key=" + getDemApiKey();
boolean isDownloadSuccessful = false;

URL url = new URL(requestURLStr);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
Expand Down Expand Up @@ -107,19 +141,21 @@ public boolean syncDownload() throws IOException {
}
outputStream.close();
Log.d(TAG,"DemDownloader: wrote "+totalBytes+" bytes to "+filename);
b = true;
isDownloadSuccessful = true;
}
catch (Exception e) {
Log.d(TAG,"DemDownloader: failed to write "+filename+" : "+e);
b = false;
isDownloadSuccessful = false;
}

connection.disconnect();

return true;
return isDownloadSuccessful;

} // syncDownload



// down a DEM async or in background
// callback will indicate success or error
// pass an object that implements a callback method
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,19 @@
import android.os.Bundle;
import android.text.Html;
import android.text.method.LinkMovementMethod;
import android.view.Gravity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import java.io.IOException;

public class ManageDroneModelsAndAPIKeyActivity extends AthenaActivity{

// private Handler mainHandler = new Handler(Looper.getMainLooper());

// Member variables for TextViews
private TextView titleTextView1;
private TextView textViewDemApiKeyStatus;
Expand All @@ -27,13 +33,22 @@ public class ManageDroneModelsAndAPIKeyActivity extends AthenaActivity{

// Member variables for Buttons
private Button applyNewDemApiKeyButton;
private Button resetApiKeyButton;
private Button loadNewDroneModelsJsonButton;
private Button resetPrefsButton;
private Button resetDroneModelsButton;

protected ApiKeyStatus apiKeyStatus;

// // Member variable for Views (separator lines)
// private View viewSep1;
// private View viewSep2;

protected enum ApiKeyStatus {
VALID,
UNKNOWN,
INVALID
}

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Expand All @@ -55,8 +70,9 @@ protected void onCreate(Bundle savedInstanceState) {

// Initialize Buttons
applyNewDemApiKeyButton = findViewById(R.id.apply_new_dem_API_key_button);
resetApiKeyButton = findViewById(R.id.reset_API_key_button);
loadNewDroneModelsJsonButton = findViewById(R.id.load_new_dronemodels_json_button);
resetPrefsButton = findViewById(R.id.reset_prefs_button);
resetDroneModelsButton = findViewById(R.id.reset_dronemodels_button);

// // Initialize Views
// viewSep1 = findViewById(R.id.view_sep_1);
Expand All @@ -65,8 +81,72 @@ protected void onCreate(Bundle savedInstanceState) {
textViewLinkObtainApiKey.setText(Html.fromHtml(getString(R.string.href_obtain_an_api_key_here), Html.FROM_HTML_MODE_COMPACT));
textViewLinkObtainApiKey.setMovementMethod(LinkMovementMethod.getInstance());

tesAPIKeyAndSetApiKeyStatus();
}

@Override
protected void onResume() {
super.onResume();
tesAPIKeyAndSetApiKeyStatus();
}

protected void tesAPIKeyAndSetApiKeyStatus() {
// demDownloader to be used for API Key validity check
// lat lon parmaters in input are ignored
DemDownloader demDownloader = new DemDownloader(this, 0.0, 0.0, 10);


new Thread(new Runnable() {
@Override
public void run() {
try {
if (demDownloader.isApiKeyValid()) {
apiKeyStatus = ApiKeyStatus.VALID;
} else {
apiKeyStatus = ApiKeyStatus.INVALID;
}
} catch (IOException e) {
// IOException indicates no internet connection available
apiKeyStatus = ApiKeyStatus.UNKNOWN;
}
updateTextViewDemApiKeyStatus();

}
}).start();

// try {
// if (demDownloader.isApiKeyValid()) {
// apiKeyStatus = ApiKeyStatus.VALID;
// } else {
// apiKeyStatus = ApiKeyStatus.INVALID;
// }
// } catch (IOException ioe) {
// // IOException indicates no internet connection available
// apiKeyStatus = ApiKeyStatus.UNKNOWN;
// }
// updateTextViewDemApiKeyStatus();
}

protected void updateTextViewDemApiKeyStatus() {
String newText = getString(R.string.dem_api_key_status) + " ";
if (apiKeyStatus == ApiKeyStatus.VALID) {
newText += "✅" + " (" + getString(R.string.status_valid) + ")";
} else if (apiKeyStatus == ApiKeyStatus.UNKNOWN) {
newText += "❓" + " (" + getString(R.string.status_unknown) + ")";
} else {
newText += "❌" + " (" + getString(R.string.status_invalid) + ")";
}
final String outText = newText;
runOnUiThread(new Runnable() {
@Override
public void run() {
textViewDemApiKeyStatus.setText(outText);
}
});
}



public void handleApplyNewDemApiKey(View view) {
// Logic for handling Apply New DEM API Key button click
}
Expand All @@ -75,7 +155,7 @@ public void handleLoadNewDroneModelsJson(View view) {
// Logic for handling Load New droneModels.json button click
}

public void handleResetPrefs(View view) {
public void handleResetDroneModels(View view) {
// Logic for handling Reset Preferences button click
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
android:layout_below="@id/titleTextView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="API Key Status: "
android:text="@string/dem_api_key_status"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:layout_marginTop="8dp"
android:gravity="center_horizontal"
Expand Down Expand Up @@ -78,9 +78,21 @@
android:textAllCaps="false"
android:layout_marginTop="16dp" />

<Button
android:id="@+id/reset_API_key_button"
android:onClick="handleResetDroneModels"
android:layout_below="@id/apply_new_dem_API_key_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:gravity="center"
android:text="@string/reset_prefs_text"
android:textAllCaps="false"
android:layout_marginTop="16dp" />

<View
android:id="@+id/view_sep_2"
android:layout_below="@id/apply_new_dem_API_key_button"
android:layout_below="@id/reset_API_key_button"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#D3D3D3"
Expand Down Expand Up @@ -141,8 +153,8 @@
android:layout_marginTop="16dp" />

<Button
android:id="@+id/reset_prefs_button"
android:onClick="handleResetPrefs"
android:id="@+id/reset_dronemodels_button"
android:onClick="handleResetDroneModels"
android:layout_below="@id/load_new_dronemodels_json_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
Expand Down
6 changes: 5 additions & 1 deletion app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,10 @@
<string name="error_nondescript">ERROR</string>
<string name="action_manage_drone_models_and_api_key">Manage Drone Models and API Key</string>
<string name="href_obtain_an_api_key_here"><![CDATA[<a href=https://opentopography.org/blog/introducing-api-keys-access-opentopography-global-datasets">Obtain An API Key Here</a>]]></string>
<string name="api_key_gibberish" translatable="false">nlhhp3yd9ud54tr3eem4akqv49wcb23i</string>
<string name="api_key_gibberish">e.g.: nlhhp3yd9ud54tr3eem4akqv49wcb23i</string>
<string name="apply_changes_button_text">Apply</string>
<string name="dem_api_key_status">API Key Status:</string>
<string name="status_valid">Valid</string>
<string name="status_invalid">Invalid</string>
<string name="status_unknown">Unknown</string>
</resources>

0 comments on commit 8c50150

Please sign in to comment.