I have been working on an Android Smart Phone application client for Nikita Noark5 Core (no.oslomet.nikita) in Java under the Java package tree for no.oslomet.nikita.api.android on a fork of Nikita Noark5 Core on https://gitlab.com/ole.aamot/nikita-noark5-core/
The code is in the following commit line:
https://gitlab.com/ole.aamot/nikita-noark5-core/-/commit/7b388febf7d1c5f8562ea33b380ab3b3d5829947
The application appears to interact with location-based services, involving JSON parsing, HTTP requests, and API integration. Key Observations:
1. AndroidManifest.xml:
* Declares the ACCESS_FINE_LOCATION permission, suggesting location-related functionality. * Specifies two activities (ItemListActivity and ItemDetailActivity) with intent filters for app launch.
2. Core Classes:
* App.java: Implements a singleton pattern for accessing application context. * HTTPHandler.java: Handles HTTP GET and POST requests, supporting token-based authorization and JSON payloads. * JSON.java: Provides a container for location-related JSON data, with support for additional properties. * Location.java: Models location-related data with fields such as id, name, latitude, and longitude. * NikitaParser.java: Parses JSON responses to extract location information and populate Location objects.
3. Areas of Improvement:
* Error Handling: Improve exception management in HTTPHandler to handle specific HTTP errors gracefully. * Code Modernization: Replace the deprecated DefaultHttpClient with HttpURLConnection or a library like OkHttp. * Threading: Ensure network operations are executed off the main thread using AsyncTask, Thread, or better, Kotlin Coroutines or WorkManager. * Security: Avoid storing sensitive data (like tokens) in plaintext. Consider encrypted storage mechanisms.
4. Potential Enhancements:
* Dependency Injection: Introduce Dagger or Hilt to manage dependencies and reduce tight coupling. * Unit Testing: Write test cases for API integration using tools like Mockito and JUnit. * User Interface: Consider Material Design principles for consistent UI/UX. ole@cdn:~/nikita-noark5-core/android$ cat app/src/main/AndroidManifest.xml <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="<http://schemas.android.com/apk/res/android>" package="no.oslomet.nikita.api.android"> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".ItemListActivity" android:label="@string/app_name" android:theme="@style/AppTheme.NoActionBar" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".ItemDetailActivity" android:label="@string/title_item_detail" android:parentActivityName=".ItemListActivity" android:theme="@style/AppTheme.NoActionBar" android:exported="true"> <meta-data android:name="android.support.PARENT_ACTIVITY" android:value="no.oslomet.nikita.api.android.ItemListActivity" /> </activity> </application>
</manifest> ole@cdn:~/nikita-noark5-core/android$ cat app/src/main/ AndroidManifest.xml java/ res/ ole@cdn:~/nikita-noark5-core/android$ cat app/src/main/java/ no/ Test.java ole@cdn:~/nikita-noark5-core/android$ cat app/src/main/java/no/oslomet/nikita/api/ android/ App.java HTTPHandler.java JSON.java Location.java NikitaParser.java ole@cdn:~/nikita-noark5-core/android$ cat app/src/main/java/no/oslomet/nikita/api/App.java package no.oslomet.nikita.api;
import android.app.Application; import android.content.Context;
public class App extends Application {
private static Application sApplication;
public static Application getApplication() { return sApplication; }
public static Context getContext() { return getApplication().getApplicationContext(); }
@Override public void onCreate() { super.onCreate(); sApplication = this; }
} ole@cdn:~/nikita-noark5-core/android$ cat app/src/main/java/no/oslomet/nikita/api/HTTPHandler.java package no.oslomet.nikita.api;
import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.List;
import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.utils.URLEncodedUtils; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.util.EntityUtils;
import android.util.Log;
public class HTTPHandler {
static String response = null; public final static int GET = 1; public final static int POST = 2;
public HTTPHandler() {
}
/* * Making service call * * @url - url to make request * * @token - base64 encrypt o the user data */ public String makeServiceCall(String url, int method) { return this.makeServiceCall(url, null, method, null); }
/* * Making service call * * @url - url to make request * * @token - base64 encript o the user data * * @method - http request method */ public String makeServiceCall(String url, String token, int method) { return this.makeServiceCall(url, token, method, null); }
/* * Making service call * * @url - url to make request * * @token - base64 encript o the user data * * @method - http request method * * @json - json with the data of the data to be post */ public String makeServiceCall(String url, String token, int method, String json) { return this.makeServiceCall(url, token, method, null, json); }
/* * Making service call * * @url - url to make request * * @method - http request method * * @params - http request params */ public String makeServiceCall(String url, String token, int method, List<NameValuePair> params, String json) { try { // http client DefaultHttpClient httpClient = new DefaultHttpClient(); HttpEntity httpEntity = null; HttpResponse httpResponse = null;
// Checking http request method type if (method == POST) { HttpPost httpPost = new HttpPost(url);
// adding post params if (params != null) { httpPost.setEntity(new UrlEncodedFormEntity(params)); } else if (json != null) { // Log.i("Eff-Json", "enviannnndo!!!"); // Log.i("Eff-Json", "Normal" + new StringEntity(json)); // Log.i("Eff-Json", "encoded" + EntityUtils.toString(new StringEntity(json), "UTF-8")); // Post the data: httpPost.setHeader("Content-Type", "application/json"); httpPost.setHeader("Authorization", "Basic " + token); // TODO: Will this need a UTF-8 codification??? httpPost.setEntity(new StringEntity(json)); // Log.i("Eff-Json", "enviado!!!"); }
httpResponse = httpClient.execute(httpPost);
} else if (method == GET) {
// appending params to url if (params != null) { String paramString = URLEncodedUtils .format(params, "utf-8"); url += "?" + paramString; } HttpGet httpGet = new HttpGet(url); httpGet.setHeader("Authorization", "Basic " + token); httpResponse = httpClient.execute(httpGet);
} httpEntity = httpResponse.getEntity(); response = EntityUtils.toString(httpEntity, "UTF-8");
} catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }
return response;
} } ole@cdn:~/nikita-noark5-core/android$ cat app/src/main/java/no/oslomet/nikita/api/ android/ App.java HTTPHandler.java JSON.java Location.java NikitaParser.java ole@cdn:~/nikita-noark5-core/android$ cat app/src/main/java/no/oslomet/nikita/api/JSON.java package no.oslomet.nikita.api;
import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map;
public class JSON {
private List<Location> locations = new ArrayList<Location>(); private Map<String, Object> additionalProperties = new HashMap<String, Object>();
/** * * @return * The locations */ public List<Location> getLocations() { return locations; }
/** * * @param locations * The locations */ public void setLocations(List<Location> locations) { this.locations = locations; }
public Map<String, Object> getAdditionalProperties() { return this.additionalProperties; }
public void setAdditionalProperty(String name, Object value) { this.additionalProperties.put(name, value); }
} ole@cdn:~/nikita-noark5-core/android$ cat app/src/main/java/no/oslomet/nikita/api/Location.java package no.oslomet.nikita.api; import java.util.HashMap; import java.util.Map;
public class Location {
public String id; public String name; public String service; public String location; public String modified; public String created; public String glat; public String glon; public String paid; public String token; public String type; public String distance; public String email; public Map<String, Object> additionalProperties = new HashMap<String, Object>();
/** * * @return * The id */ public String getId() { return id; }
/** * * @param id * The id */ public void setId(String id) { this.id = id; }
/** * * @return * The name */ public String getName() { return name; }
/** * * @param name * The name */ public void setName(String name) { this.name = name; }
/** * * @return * The service */ public String getService() { return service; }
/** * * @param service * The service */ public void setService(String service) { this.service = service; }
/** * * @return * The location */ public String getLocation() { return location; }
/** * * @param location * The location */ public void setLocation(String location) { this.location = location; }
/** * * @return * The modified */ public String getModified() { return modified; }
/** * * @param modified * The modified */ public void setModified(String modified) { this.modified = modified; }
/** * * @return * The created */ public String getCreated() { return created; }
/** * * @param created * The created */ public void setCreated(String created) { this.created = created; }
/** * * @return * The glat */ public String getGlat() { return glat; }
/** * * @param glat * The glat */ public void setGlat(String glat) { this.glat = glat; }
/** * * @return * The glon */ public String getGlon() { return glon; }
/** * * @param glon * The glon */ public void setGlon(String glon) { this.glon = glon; }
/** * * @return * The paid */ public String getPaid() { return paid; }
/** * * @param paid * The paid */ public void setPaid(String paid) { this.paid = paid; }
/** * * @return * The token */ public String getToken() { return token; }
/** * * @param token * The token */ public void setToken(String token) { this.token = token; }
/** * * @return * The type */ public String getType() { return type; }
/** * * @param type * The type */ public void setType(String type) { this.type = type; }
/** * * @return * The distance */ public String getDistance() { return distance; }
/** * * @param distance * The distance */ public void setDistance(String distance) { this.distance = distance; }
/** * * @return * The email */ public String getEmail() { return email; }
/** * * @param email * The email */ public void setEmail(String email) { this.email = email; }
public Map<String, Object> getAdditionalProperties() { return this.additionalProperties; }
public void setAdditionalProperty(String name, Object value) { this.additionalProperties.put(name, value); }
} ole@cdn:~/nikita-noark5-core/android$ cat app/src/main/java/no/oslomet/nikita/api/Location.java app/ .gradle/ gradle.properties gradlew.bat README.md settings.gradle build.gradle gradle/ gradlew LICENSE release ole@cdn:~/nikita-noark5-core/android$ cat app/src/main/java/no/oslomet/nikita/api/ android/ App.java HTTPHandler.java JSON.java Location.java NikitaParser.java ole@cdn:~/nikita-noark5-core/android$ cat app/src/main/java/no/oslomet/nikita/api/NikitaParser.java package no.oslomet.nikita.api;
import org.json.JSONArray; import org.json.JSONObject;
import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.URL;
import no.oslomet.nikita.api.Location;
public class NikitaParser {
public static Location getJSONObject(String strJSONValue) throws Exception {
Location loc = new Location(); String strParsedValue;
JSONObject jsonObject = new JSONObject(strJSONValue); JSONObject object = jsonObject.getJSONObject("locations"); String name = object.getString("name"); String service = object.getString("service"); String location = object.getString("location");
// strParsedValue = "Name value => " + name; // strParsedValue += "\n Service value => " + name;
JSONObject subObject = object.getJSONObject("sub"); JSONArray subArray = subObject.getJSONArray("sub1");
loc.setName(name); loc.setService(service); loc.setLocation(location);
return loc; }
} ole@cdn:~/nikita-noark5-core/android$ cat app/src/main/java/Test.java import no.oslomet.nikita.api.HTTPHandler; public class Test { public static void main(String args[]) { HTTPHandler sh = new HTTPHandler(); // Making a request to url and getting response String url = "http://localhost:8092/api/android"; String jsonStr = sh.makeServiceCall(url, HTTPHandler.GET); System.out.print(jsonStr); } } ole@cdn:~/nikita-noark5-core/android$
What is the status of nikita.oslomet.no?
Is there another public machine with a working and data populated instance of Nikita Noark5 Core, so we can replace url "http://localhost:8092/api/android" with a central archive from the Android API, or do you think Nikita could run on a smart phone on localhost on operating systems like Android?
You may want to begin developing or supporting frontends such as Android in smart phone and pad, so that smart clients can access Nikita Archives as the Archive Roles such as Archiver, User or Admin.
The latest smart phone with Android 16 is available as Google Pixel 9 from Alphabet, Inc. with Play Developer Console on https://play.google.com/console/u/0/developers for registered developers and https://play.google.com/ for eligble smart phone and pads. I either recommend distributing Nikita's app in Google Play or as .apk files served on a Web Server over HTTPS as the last method require the user to manually allow/permit installation from 3rd Party Source and gives Google less control over your application.
See https://developer.android.com/ for the Open Android Source Project and Android Studio for prototyping and Virtual Device testing.
See google-android-cmdline-tools-13.0-installer - Google's Android SDK Command-line Tools (13.0) Installer in Debian GNU/Linux.
WIll you accept my Android code into Nikita, Petter and Thomas?
Best, Ole Aamot