diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml
index e9d68e7d..00fbb194 100644
--- a/src/main/AndroidManifest.xml
+++ b/src/main/AndroidManifest.xml
@@ -21,7 +21,7 @@
-
+
diff --git a/src/main/java/org/medicmobile/webapp/mobile/EmbeddedBrowserActivity.java b/src/main/java/org/medicmobile/webapp/mobile/EmbeddedBrowserActivity.java
index dafa0975..56b3dfd4 100644
--- a/src/main/java/org/medicmobile/webapp/mobile/EmbeddedBrowserActivity.java
+++ b/src/main/java/org/medicmobile/webapp/mobile/EmbeddedBrowserActivity.java
@@ -21,25 +21,50 @@
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.Uri;
+import android.os.Build;
import android.os.Bundle;
+
+import android.os.StrictMode;
+import android.util.Base64;
+import android.util.Log;
import android.view.View;
import android.view.Window;
import android.webkit.ConsoleMessage;
+import android.webkit.CookieManager;
import android.webkit.GeolocationPermissions;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
+import android.webkit.WebViewClient;
+import android.widget.Button;
import android.widget.Toast;
-
import androidx.core.content.ContextCompat;
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+import java.io.BufferedReader;
+
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLDecoder;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
import java.util.Optional;
@SuppressWarnings({ "PMD.GodClass", "PMD.TooManyMethods" })
public class EmbeddedBrowserActivity extends Activity {
-
+ Button download_button;
+ Button upload_button;
+ public String role = "Placeholder";
private WebView container;
private SettingsStore settings;
private String appUrl;
@@ -59,13 +84,13 @@ public void onReceiveValue(String result) {
}
}
};
+ private List userData;
-//> ACTIVITY LIFECYCLE METHODS
+ //> ACTIVITY LIFECYCLE METHODS
@SuppressLint("ClickableViewAccessibility")
@Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
-
trace(this, "Starting webview...");
this.filePickerHandler = new FilePickerHandler(this);
@@ -80,10 +105,36 @@ public void onReceiveValue(String result) {
this.settings = SettingsStore.in(this);
this.appUrl = settings.getAppUrl();
-
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
+
setContentView(R.layout.main);
+ download_button = findViewById(R.id.download_button);
+ upload_button = findViewById(R.id.upload_button);
+
+ download_button.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ String userName = getUserData().get(0);
+
+ container.evaluateJavascript("console.log('"+ "username:"+ userName + "')", null);
+ String script = "window.PouchDB('medic-user-"+ userName+"')" +
+ ".allDocs({include_docs: true, attachments: true})" +
+ ".then(result => medicmobile_android.saveDocs(JSON.stringify(result),'"+userName+"'));";
+ container.evaluateJavascript(script, null);
+ }
+ });
+ Log.d("Screen", getApplicationContext().toString());
+
+ upload_button.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent i2 = new Intent(Intent.ACTION_GET_CONTENT);
+ i2.setType("*/*");
+ i2.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
+ startActivityForResult(i2, 106);
+ }
+ });
// Add an alarming red border if using configurable (i.e. dev)
// app with a medic production server.
if (settings.allowsConfiguration() && appUrl != null && appUrl.contains("app.medicmobile.org")) {
@@ -101,9 +152,9 @@ public void onReceiveValue(String result) {
container = findViewById(R.id.wbvMain);
getFragmentManager()
- .beginTransaction()
- .add(new OpenSettingsDialogFragment(container), OpenSettingsDialogFragment.class.getName())
- .commit();
+ .beginTransaction()
+ .add(new OpenSettingsDialogFragment(container), OpenSettingsDialogFragment.class.getName())
+ .commit();
configureUserAgent();
@@ -128,6 +179,56 @@ public void onReceiveValue(String result) {
if (isValidNavigationUrl(appUrl, recentNavigation)) {
container.loadUrl(recentNavigation);
}
+ container.setWebViewClient(new WebViewClient(){
+ @Override
+ public boolean shouldOverrideUrlLoading(WebView view, String url) {
+ Log.d("URL used in the client.", url);
+ if (!url.contains("login") ) {
+ upload_button.setVisibility(View.VISIBLE);
+ download_button.setVisibility(View.VISIBLE);
+ role = getUserData().get(1);
+ role = role.substring(1, role.length() - 1);
+ boolean isUpdateRole = role != "Placeholder" && role.equals("chw_supervisor");
+ boolean isDownloadRole = role != "Placeholder" && role.equals("chw");
+ if (isDownloadRole){
+ upload_button.setVisibility(View.GONE);
+ }else if (isUpdateRole){
+ download_button.setVisibility(View.GONE);
+ }
+ } else {
+ upload_button.setVisibility(View.GONE);
+ download_button.setVisibility(View.GONE);
+ }
+ return super.shouldOverrideUrlLoading(view, url);
+ }
+ @Override
+ public void doUpdateVisitedHistory(WebView view, String url, boolean isReload){
+ if (!Objects.isNull(url) && !url.contains("report") && !url.contains("login") && url.split("/").length > 3) {
+ Log.d(String.valueOf((url.split("/").length)),"printing URL ...");
+ upload_button.setVisibility(View.VISIBLE);
+ download_button.setVisibility(View.VISIBLE);
+ if (getUserData()!=null){
+ role = getUserData().get(1);
+ role = role.substring(1, role.length() - 1);
+ boolean isUpdateRole = role != "Placeholder" && role.equals("chw_supervisor");
+ boolean isDownloadRole = role != "Placeholder" && role.equals("chw");
+ if (isDownloadRole){
+ upload_button.setVisibility(View.GONE);
+ }else if (isUpdateRole){
+ download_button.setVisibility(View.GONE);
+ }
+ }
+ } else {
+ upload_button.setVisibility(View.GONE);
+ download_button.setVisibility(View.GONE);
+ }
+ super.doUpdateVisitedHistory(view,url,isReload);
+ }
+ @Override
+ public void onPageFinished(WebView view, String url) {
+ //page has finished loading
+ }
+ });
}
@SuppressWarnings("PMD.CallSuperFirst")
@@ -136,13 +237,17 @@ protected void onStart() {
trace(this, "onStart() :: Checking Crosswalk migration ...");
XWalkMigration xWalkMigration = new XWalkMigration(this.getApplicationContext());
if (xWalkMigration.hasToMigrate()) {
+
log(this, "onStart() :: Running Crosswalk migration ...");
isMigrationRunning = true;
Intent intent = new Intent(this, UpgradingActivity.class)
- .putExtra("isClosable", false)
- .putExtra("backPressedMessage", getString(R.string.waitMigration));
+ .putExtra("isClosable", false)
+ .putExtra("backPressedMessage", getString(R.string.waitMigration));
startActivity(intent);
xWalkMigration.run();
+ role = getUserData().get(0);
+ Log.d("Role is ", role);
+
} else {
trace(this, "onStart() :: Crosswalk installation not found - skipping migration");
}
@@ -175,6 +280,7 @@ protected void onStop() {
backButtonHandler);
}
+ @SuppressLint("Recycle")
@Override
protected void onActivityResult(int requestCd, int resultCode, Intent intent) {
Optional requestCodeOpt = RequestCode.valueOf(requestCd);
@@ -190,6 +296,21 @@ protected void onActivityResult(int requestCd, int resultCode, Intent intent) {
trace(this, "onActivityResult() :: requestCode=%s, resultCode=%s", requestCode.name(), resultCode);
switch (requestCode) {
+ case PICK_FILE_REQUEST:
+ if (resultCode == RESULT_OK && intent != null) {
+ if(intent.getClipData() != null) {
+ int count = intent.getClipData().getItemCount();
+ int currentItem = 0;
+ while(currentItem < count) {
+ Uri data_uri = intent.getClipData().getItemAt(currentItem).getUri();
+ uploadFile(data_uri, currentItem);
+ currentItem = currentItem + 1;
+ }
+ } else{
+ Uri data_uri = intent.getData();
+ uploadFile(data_uri, 1);
+ }
+ }
case FILE_PICKER_ACTIVITY:
this.filePickerHandler.processResult(resultCode, intent);
return;
@@ -214,11 +335,38 @@ protected void onActivityResult(int requestCd, int resultCode, Intent intent) {
} catch (Exception ex) {
String action = intent == null ? null : intent.getAction();
warn(ex, "Problem handling intent %s (%s) with requestCode=%s & resultCode=%s",
- intent, action, requestCode.name(), resultCode);
+ intent, action, requestCode.name(), resultCode);
}
}
-
-//> ACCESSORS
+ private void uploadFile(Uri data_uri, int currentItem){
+ String content;
+ try {
+ InputStream in = getContentResolver().openInputStream(data_uri);
+ BufferedReader r = new BufferedReader(new InputStreamReader(in));
+ StringBuilder total = new StringBuilder();
+ for (String line; (line = r.readLine()) != null; ) {
+ total.append(line);
+ }
+ if (Build.VERSION.SDK_INT > 9) {
+ StrictMode.ThreadPolicy policy =
+ new StrictMode.ThreadPolicy.Builder().permitAll().build();
+ StrictMode.setThreadPolicy(policy);
+ }
+ content =total.toString().replaceAll("\"total_rows\".*\"rows\":","\"docs\":");
+ String script = "new PouchDB('temp')" +
+ ".bulkDocs("+content+");";
+ container.evaluateJavascript(script, null);
+ String script_sync = "window.PouchDB('temp')" +
+ ".replicate.to('"+appUrl+"/medic').then(result =>" +
+ "medicmobile_android.toastResult('Uploaded file number "+(currentItem+1)+" Successfully')).catch(err =>" +
+ "medicmobile_android.toastResult(JSON.stringify(err)));";
+ container.evaluateJavascript(script_sync, null);
+ }catch (Exception e) {
+ warn(e, "Could not open the specified file");
+ toast("Could not open the specified file");
+ }
+ }
+ //> ACCESSORS
MrdtSupport getMrdtSupport() {
return this.mrdt;
}
@@ -230,8 +378,7 @@ SmsSender getSmsSender() {
ChtExternalAppHandler getChtExternalAppHandler() {
return this.chtExternalAppHandler;
}
-
-//> PUBLIC API
+ //> PUBLIC API
public void evaluateJavascript(final String js) {
evaluateJavascript(js, true);
}
@@ -272,17 +419,57 @@ public boolean getLocationPermissions() {
trace(this, "getLocationPermissions() :: Fine or Coarse location not granted before, requesting access...");
startActivityForResult(
- new Intent(this, RequestLocationPermissionActivity.class),
- RequestCode.ACCESS_LOCATION_PERMISSION.getCode()
+ new Intent(this, RequestLocationPermissionActivity.class),
+ RequestCode.ACCESS_LOCATION_PERMISSION.getCode()
);
return false;
}
-//> PRIVATE HELPERS
+ //> PRIVATE HELPERS
private void locationRequestResolved() {
evaluateJavascript("window.CHTCore.AndroidApi.v1.locationPermissionRequestResolved();");
}
+ public List getUserData(){
+ List userData = new ArrayList<>();
+ try {
+ String cookies = CookieManager.getInstance().getCookie(appUrl);
+ if (Objects.isNull(cookies)){
+ return null;
+ }
+ Log.d("updating user data", ": updated");
+
+ if ( cookies != null && !cookies.isEmpty()){
+ String encodedUserCtxCookie = Arrays.stream(cookies.split(";"))
+ .map(field -> field.split("="))
+ .filter(pair -> "userCtx".equals(pair[0].trim()))
+ .map(pair -> pair[1].trim())
+ .findAny()
+ .get();
+ String userCtxData = URLDecoder.decode(encodedUserCtxCookie, "utf-8")
+ .replace("{", "")
+ .replace("}", "");
+ String userName = Arrays.stream(userCtxData.split(","))
+ .map(field -> field.split(":"))
+ .filter(pair -> "\"name\"".equals(pair[0].trim()))
+ .map(pair -> pair[1].replace("\"", "").trim())
+ .findAny()
+ .get();
+ userData.add(userName);
+ role = (Arrays.stream(userCtxData.split(","))
+ .map(field -> field.split(":"))
+ .filter(pair -> "\"roles\"".equals(pair[0].trim()))
+ .map(pair -> pair[1].replace("\"", "").trim())
+ .findAny()
+ .get());
+ userData.add(role);
+ return userData;
+ }
+ } catch (UnsupportedEncodingException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
private void processChtExternalAppResult(int resultCode, Intent intentData) {
String script = this.chtExternalAppHandler.processResult(resultCode, intentData);
trace(this, "ChtExternalAppHandler :: Executing JavaScript: %s", script);
@@ -311,10 +498,10 @@ private void processStoragePermissionResult(int resultCode, Intent intent) {
}
trace(
- this,
- "EmbeddedBrowserActivity :: No handling for trigger: %s, requestCode: %s",
- triggerClass,
- RequestCode.ACCESS_STORAGE_PERMISSION.name()
+ this,
+ "EmbeddedBrowserActivity :: No handling for trigger: %s, requestCode: %s",
+ triggerClass,
+ RequestCode.ACCESS_STORAGE_PERMISSION.name()
);
}
@@ -398,14 +585,15 @@ private void registerRetryConnectionBroadcastReceiver() {
registerReceiver(broadcastReceiver, new IntentFilter("retryConnection"));
}
-//> ENUMS
+ //> ENUMS
public enum RequestCode {
ACCESS_LOCATION_PERMISSION(100),
ACCESS_STORAGE_PERMISSION(101),
ACCESS_SEND_SMS_PERMISSION(102),
CHT_EXTERNAL_APP_ACTIVITY(103),
GRAB_MRDT_PHOTO_ACTIVITY(104),
- FILE_PICKER_ACTIVITY(105);
+ FILE_PICKER_ACTIVITY(105),
+ PICK_FILE_REQUEST(106);
private final int requestCode;
@@ -415,9 +603,9 @@ public enum RequestCode {
public static Optional valueOf(int code) {
return Arrays
- .stream(RequestCode.values())
- .filter(e -> e.getCode() == code)
- .findFirst();
+ .stream(RequestCode.values())
+ .filter(e -> e.getCode() == code)
+ .findFirst();
}
public int getCode() {
diff --git a/src/main/java/org/medicmobile/webapp/mobile/MedicAndroidJavascript.java b/src/main/java/org/medicmobile/webapp/mobile/MedicAndroidJavascript.java
index aac1e627..605bdb56 100644
--- a/src/main/java/org/medicmobile/webapp/mobile/MedicAndroidJavascript.java
+++ b/src/main/java/org/medicmobile/webapp/mobile/MedicAndroidJavascript.java
@@ -1,9 +1,14 @@
package org.medicmobile.webapp.mobile;
+import static android.os.Environment.DIRECTORY_DOCUMENTS;
+import static android.os.Environment.getExternalStorageDirectory;
+import static android.os.Environment.getExternalStoragePublicDirectory;
+
import android.annotation.SuppressLint;
import android.app.ActivityManager;
import android.app.ActivityManager.MemoryInfo;
import android.app.DatePickerDialog;
+import android.content.Context;
import android.content.pm.PackageInfo;
import android.net.ConnectivityManager;
import android.net.NetworkCapabilities;
@@ -11,15 +16,22 @@
import android.net.TrafficStats;
import android.net.Uri;
import android.os.Process;
+import android.util.Log;
+import android.webkit.JavascriptInterface;
import android.widget.DatePicker;
import android.os.Build;
import android.os.Environment;
import android.os.StatFs;
+import android.widget.Toast;
import java.io.BufferedReader;
+import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileWriter;
import java.io.IOException;
+import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.Reader;
@@ -28,10 +40,15 @@
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
+import java.time.LocalDateTime;
+import java.time.temporal.ChronoUnit;
import java.util.Calendar;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.Map;
+import java.util.Objects;
+import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@@ -40,6 +57,7 @@
import static java.util.Calendar.YEAR;
import static java.util.Locale.UK;
import static org.medicmobile.webapp.mobile.MedicLog.log;
+import static org.medicmobile.webapp.mobile.MedicLog.warn;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
@@ -74,7 +92,7 @@ public void setConnectivityManager(ConnectivityManager connectivityManager) {
this.connectivityManager = connectivityManager;
}
-//> JavascriptInterface METHODS
+ //> JavascriptInterface METHODS
@android.webkit.JavascriptInterface
public String getAppVersion() {
try {
@@ -86,6 +104,114 @@ public String getAppVersion() {
}
}
+ @JavascriptInterface
+ public void toastResult(String result){
+ Toast.makeText(parent, result, Toast.LENGTH_LONG).show();
+ }
+ @JavascriptInterface
+ public void saveDocs(String docs, String username) throws IOException{
+ JSONArray newDocs = new JSONArray();
+ try {
+ docs = docs.replaceAll("\\\\/", "/");
+ JSONObject docs_obj = new JSONObject(docs);
+ JSONArray docs_list = docs_obj.getJSONArray("rows");
+ for (int i = 0; i < docs_list.length(); i++) {
+ docs_list.getJSONObject(i).remove("key");
+ docs_list.getJSONObject(i).remove("value");
+ docs_list.getJSONObject(i).getJSONObject("doc").remove("_rev");
+ if(docs_list.getJSONObject(i).has("_rev")){
+ docs_list.getJSONObject(i).remove("_rev");
+ }
+ if(docs_list.getJSONObject(i).getJSONObject("doc").has("doc")){
+ docs_list.remove(i);
+ }
+ if (docs_list.getJSONObject(i).getString("id").startsWith("form")|| docs_list.getJSONObject(i).getString("id").equals("settings") || docs_list.getJSONObject(i).getString("id").startsWith("service") ||docs_list.getJSONObject(i).getString("id").equals("resources") || docs_list.getJSONObject(i).getString("id").equals("branding") || docs_list.getJSONObject(i).getString("id").startsWith("_design") || docs_list.getJSONObject(i).getJSONObject("doc").has("type") && (docs_list.getJSONObject(i).getJSONObject("doc").get("type").toString().equals("translations") || docs_list.getJSONObject(i).getJSONObject("doc").get("type").toString().equals("target"))) {
+ Log.d("Translations: ", "found");
+ }else{
+ if(docs_list.getJSONObject(i).getJSONObject("doc").has("_attachments")){
+ String contentType = docs_list.getJSONObject(i).getJSONObject("doc").getJSONObject("_attachments").getJSONObject("content").getString("content_type");
+ String digest = docs_list.getJSONObject(i).getJSONObject("doc").getJSONObject("_attachments").getJSONObject("content").getString("digest");
+ docs_list.getJSONObject(i).getJSONObject("doc").getJSONObject("_attachments").getJSONObject("content").remove("content_type");
+ docs_list.getJSONObject(i).getJSONObject("doc").getJSONObject("_attachments").getJSONObject("content").remove("digest");
+ contentType = "application/xml";
+ digest= digest.replace("\\\\/","/");
+ docs_list.getJSONObject(i).getJSONObject("doc").getJSONObject("_attachments").getJSONObject("content").put("content_type", contentType);
+ docs_list.getJSONObject(i).getJSONObject("doc").getJSONObject("_attachments").getJSONObject("content").put("revpos", 1);
+ docs_list.getJSONObject(i).getJSONObject("doc").getJSONObject("_attachments").getJSONObject("content").put("digest", digest);
+
+ Log.d("application / content", docs_list.getJSONObject(i).getJSONObject("doc").getJSONObject("_attachments").getJSONObject("content").getString("content_type").toString());
+ }
+ Iterator keys = docs_list.getJSONObject(i).getJSONObject("doc").keys();
+ while(keys.hasNext()) {
+ String key = keys.next();
+ docs_list.getJSONObject(i).put(key,docs_list.getJSONObject(i).getJSONObject("doc").get(key));
+ }
+ docs_list.getJSONObject(i).remove("doc");
+
+ if (docs_list.getJSONObject(i).has("id")){
+ docs_list.getJSONObject(i).remove("id");
+ }
+ newDocs.put(docs_list.getJSONObject(i));
+ }
+
+ }
+ } catch (JSONException e) {
+ Log.d("Error json type", "json file");
+ e.printStackTrace();
+ }
+ if (newDocs != null && newDocs.length() > 0 ){
+ docs= "{\"docs\":"+newDocs.toString()+"}";
+ }
+ File file = null;
+ DateFormat df = new SimpleDateFormat("yyyyMMddhhmmss");
+ Log.d("storage", String.valueOf(Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())));
+ Log.d("version", String.valueOf(Build.VERSION.SDK_INT));
+ File cht_data = new File(this.parent.getExternalFilesDir("Documents")+"/cht_data/");
+ if (!cht_data.exists()){
+ cht_data.mkdirs();
+ }
+ if (android.os.Build.VERSION.SDK_INT >= 26) {
+ file = new File(this.parent.getExternalFilesDir("Documents")+"/cht_data/", username+"_"+ LocalDateTime.now()
+ .truncatedTo(ChronoUnit.SECONDS)
+ .toString()
+ .replace("-","")
+ .replace(":","")+ ".txt");
+ }
+ else {
+ file = new File(this.parent.getExternalFilesDir("Documents")+"/cht_data/", username+"_"+LocalDateTime.now().truncatedTo(ChronoUnit.SECONDS)
+ .toString()
+ .replace("-","")
+ .replace(":","")+ ".txt");
+ }
+ Log.d("file", file.toString());
+ if(!file.getParentFile().exists()){
+ Log.d("Creating parent", file.getParent().toString());
+ file.getParentFile().mkdirs();
+ }
+ if(!file.exists()){
+ try {
+ file.createNewFile();
+ }catch (Exception e){
+ e.printStackTrace();
+ }
+ }
+ Log.d("file exists", String.valueOf(file.exists()));
+ try {
+ FileWriter fileWriter = new FileWriter(file);
+ BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
+ bufferedWriter.write(docs);
+ bufferedWriter.close();
+ toastResult("Download Completed");
+ } catch (FileNotFoundException e){
+ toastResult("Could not find the file");
+ e.printStackTrace();
+ } catch (IOException e) {
+ toastResult("Could not write the file to storage");
+ e.printStackTrace();
+ }
+
+
+ }
@android.webkit.JavascriptInterface
public void playAlert() {
try {
@@ -302,8 +428,25 @@ public String getDeviceInfo() {
return jsonError("Problem fetching device info: ", ex);
}
}
-
-//> PRIVATE HELPER METHODS
+ public JSONObject parseJSON(JSONObject json)
+ {
+ Iterator iter = json.keys();
+ while (iter.hasNext())
+ {
+ String key = iter.next();
+ if (key.equals("-xmlns:i") ||
+ key.equals("-i:nil") ||
+ key.equals("-xmlns:d4p1") ||
+ key.equals("-i:type") ||
+ key.equals("#text")) // I want to delete items with those ID strings
+ {
+ json.remove(key);
+ }
+ //Object value = json.get(key);
+ }
+ return json;
+ }
+ //> PRIVATE HELPER METHODS
private void datePicker(String targetElement, Calendar initialDate) {
// Remove single-quotes from the `targetElement` CSS selecter, as
// we'll be using these to enclose the entire string in JS. We
@@ -337,8 +480,8 @@ public void onDateSet(DatePicker view, int year, int month, int day) {
private static HashMap getCPUInfo() throws IOException {
try(
- Reader fileReader = new InputStreamReader(new FileInputStream("/proc/cpuinfo"), StandardCharsets.UTF_8);
- BufferedReader bufferedReader = new BufferedReader(fileReader);
+ Reader fileReader = new InputStreamReader(new FileInputStream("/proc/cpuinfo"), StandardCharsets.UTF_8);
+ BufferedReader bufferedReader = new BufferedReader(fileReader);
) {
String line;
HashMap output = new HashMap();
@@ -376,7 +519,7 @@ private void logException(Exception ex) {
parent.errorToJsConsole("Exception thrown in JavascriptInterface function: %s", stacktrace);
}
-//> STATIC HELPERS
+ //> STATIC HELPERS
private static String jsonError(String message, Exception ex) {
return jsonError(message + ex.getClass() + ": " + ex.getMessage());
}
diff --git a/src/main/res/layout/main.xml b/src/main/res/layout/main.xml
index fadffce8..a9032df8 100644
--- a/src/main/res/layout/main.xml
+++ b/src/main/res/layout/main.xml
@@ -3,7 +3,27 @@
android:id="@+id/lytWebView"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
-
+
+
+
+
+