summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorParménides GV <parmegv@sdf.org>2013-01-31 22:12:21 +0100
committerParménides GV <parmegv@sdf.org>2013-01-31 22:12:21 +0100
commit92c32b0b96938009af55ed28920472f22a4614ee (patch)
tree8b714947e35330ba92d618849e60b8ce5bccc6db
parentd21e8390e90437f0d053374f8e304ca3f592beb9 (diff)
Problems with downloaded file, the emulator cannot find the file
downloaded. Seen http://code.google.com/p/android/issues/detail?id=18462 and decided to look for another solution. First solution thought (and going to be the next test): HTTP Get request :)
-rw-r--r--AndroidManifest.xml6
-rw-r--r--assets/urls/bitmask.url6
-rw-r--r--res/layout/activity_provider_list.xml10
-rw-r--r--src/se/leap/leapclient/Dashboard.java4
-rw-r--r--src/se/leap/leapclient/ProviderAPI.java15
-rw-r--r--src/se/leap/leapclient/ProviderListActivity.java187
-rw-r--r--src/se/leap/leapclient/ProviderListContent.java77
-rw-r--r--src/se/leap/leapclient/ProviderListFragment.java150
8 files changed, 453 insertions, 2 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 7162576a..438b6887 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -25,6 +25,7 @@
<!-- <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- <uses-permission android:name="com.android.vending.BILLING" /> -->
@@ -150,6 +151,11 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
+
+ <activity
+ android:name="se.leap.leapclient.ProviderListActivity"
+ android:label="@string/app" >
+ </activity>
</application>
</manifest> \ No newline at end of file
diff --git a/assets/urls/bitmask.url b/assets/urls/bitmask.url
new file mode 100644
index 00000000..132e295d
--- /dev/null
+++ b/assets/urls/bitmask.url
@@ -0,0 +1,6 @@
+{
+ "name" : "bitmask",
+ "json_provider" : "https://bitmask.net/provider.json",
+ "cert" : "https://bitmask.net/1/cert",
+ "json_eip_service" : "https://api.bitmask.net:4430/1/config/eip-service.json"
+} \ No newline at end of file
diff --git a/res/layout/activity_provider_list.xml b/res/layout/activity_provider_list.xml
new file mode 100644
index 00000000..6a6dafec
--- /dev/null
+++ b/res/layout/activity_provider_list.xml
@@ -0,0 +1,10 @@
+<fragment xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:id="@+id/provider_list"
+ android:name="se.leap.leapclient.ProviderListFragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_marginLeft="16dp"
+ android:layout_marginRight="16dp"
+ tools:context=".ProviderListActivity"
+ tools:layout="@android:layout/list_content" />
diff --git a/src/se/leap/leapclient/Dashboard.java b/src/se/leap/leapclient/Dashboard.java
index 7d0b5e0f..84ddab27 100644
--- a/src/se/leap/leapclient/Dashboard.java
+++ b/src/se/leap/leapclient/Dashboard.java
@@ -37,8 +37,8 @@ public class Dashboard extends Activity {
preferences = getPreferences(MODE_PRIVATE);
// FIXME provider data!! get parmegv's work so we can stop (or lessen) faking it
- if ( !preferences.contains("provider") )
- fixmePrefsFaker(preferences);
+ if (preferences.contains("provider") )
+ startActivity(new Intent(this, ProviderListActivity.class));
// Get our provider
provider = Provider.getInstance(preferences);
diff --git a/src/se/leap/leapclient/ProviderAPI.java b/src/se/leap/leapclient/ProviderAPI.java
new file mode 100644
index 00000000..6d52e44f
--- /dev/null
+++ b/src/se/leap/leapclient/ProviderAPI.java
@@ -0,0 +1,15 @@
+package se.leap.leapclient;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+
+public class ProviderAPI extends Service {
+
+ @Override
+ public IBinder onBind(Intent arg0) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}
diff --git a/src/se/leap/leapclient/ProviderListActivity.java b/src/se/leap/leapclient/ProviderListActivity.java
new file mode 100644
index 00000000..4964a1fd
--- /dev/null
+++ b/src/se/leap/leapclient/ProviderListActivity.java
@@ -0,0 +1,187 @@
+package se.leap.leapclient;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import se.leap.leapclient.ProviderListContent;
+import se.leap.leapclient.ProviderListContent.ProviderItem;
+import android.app.DownloadManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.res.AssetManager;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Environment;
+import android.support.v4.app.FragmentActivity;
+
+
+/**
+ * An activity representing a list of Providers. This activity
+ * has different presentations for handset and tablet-size devices. On
+ * handsets, the activity presents a list of items, which when touched,
+ * lead to a {@link DashboardActivity} representing
+ * item details. On tablets, the activity presents the list of items and
+ * item details side-by-side using two vertical panes.
+ * <p>
+ * The activity makes heavy use of fragments. The list of items is a
+ * {@link ProviderListFragment} and the item details
+ * (if present) is a {@link DashboardFragment}.
+ * <p>
+ * This activity also implements the required
+ * {@link ProviderListFragment.Callbacks} interface
+ * to listen for item selections.
+ */
+public class ProviderListActivity extends FragmentActivity
+ implements ProviderListFragment.Callbacks {
+
+ /**
+ * Whether or not the activity is in two-pane mode, i.e. running on a tablet
+ * device.
+ */
+ private boolean mTwoPane;
+
+ private static SharedPreferences preferences;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_provider_list);
+
+ preferences = getPreferences(MODE_PRIVATE);
+
+ loadPreseededProviders();
+
+ // TODO: If exposing deep links into your app, handle intents here.
+ }
+
+ private void loadPreseededProviders() {
+ AssetManager asset_manager = getAssets();
+ String[] urls_filepaths = null;
+ try {
+ String url_files_folder = "urls";
+ //TODO Put that folder in a better place (also inside the "for")
+ urls_filepaths = asset_manager.list(url_files_folder);
+ String provider_name = "";
+ for(String url_filepath : urls_filepaths)
+ {
+ provider_name = url_filepath.subSequence(0, url_filepath.indexOf(".")).toString();
+ if(ProviderListContent.ITEMS.isEmpty()) //TODO I have to implement a way of checking if a provider new or is already present in that ITEMS list
+ ProviderListContent.addItem(new ProviderItem(provider_name, asset_manager.open(url_files_folder + "/" + url_filepath)));
+ }
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Callback method from {@link ProviderListFragment.Callbacks}
+ * indicating that the item with the given ID was selected.
+ */
+ @Override
+ public void onItemSelected(String id) {
+ if (mTwoPane) {
+
+ } else {
+ // In single-pane mode, simply start the detail activity
+ // for the selected item ID.
+
+ Iterator<ProviderItem> preseeded_providers_iterator = ProviderListContent.ITEMS.iterator();
+ while(preseeded_providers_iterator.hasNext())
+ {
+ ProviderItem current_provider_item = preseeded_providers_iterator.next();
+ if(current_provider_item.id.equalsIgnoreCase(id))
+ {
+ ArrayList<String> downloaded_files = downloadFiles(current_provider_item);
+ try {
+ parseToSharedPrefs(downloaded_files);
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ }
+
+ Intent dashboardIntent = new Intent(this, Dashboard.class);
+ startActivity(dashboardIntent);
+ }
+ }
+
+ private void parseToSharedPrefs(ArrayList<String> downloaded_files) throws IOException {
+ SharedPreferences.Editor sharedPreferencesEditor = preferences.edit();
+
+ for(int i = 0; i < downloaded_files.size(); i++)
+ {
+ String type_and_filename = downloaded_files.get(i);
+ String filename = type_and_filename.substring(type_and_filename.indexOf(":")+1, type_and_filename.length());
+
+ String file_contents = readFileAsString(filename, null);
+
+ if(downloaded_files.get(i).startsWith("provider:"))
+ sharedPreferencesEditor.putString("provider", file_contents);
+ else if(downloaded_files.get(i).startsWith("provider:"))
+ sharedPreferencesEditor.putString("eip", file_contents);
+
+ sharedPreferencesEditor.commit();
+ }
+ }
+
+ public static String readFileAsString(String fileName, String charsetName)
+ throws java.io.IOException {
+ java.io.InputStream is = new java.io.FileInputStream(fileName);
+ try {
+ final int bufsize = 4096;
+ int available = is.available();
+ byte data[] = new byte[available < bufsize ? bufsize : available];
+ int used = 0;
+ while (true) {
+ if (data.length - used < bufsize) {
+ byte newData[] = new byte[data.length << 1];
+ System.arraycopy(data, 0, newData, 0, used);
+ data = newData;
+ }
+ int got = is.read(data, used, data.length - used);
+ if (got <= 0)
+ break;
+ used += got;
+ }
+ return charsetName != null ? new String(data, 0, used, charsetName)
+ : new String(data, 0, used);
+ } finally {
+ is.close();
+ }
+ }
+
+ private ArrayList<String> downloadFiles(ProviderItem current_provider_item) {
+ ArrayList<String> paths_to_downloaded_files = new ArrayList<String>();
+
+ paths_to_downloaded_files.add(downloadProviderJSON("provider_json", current_provider_item.provider_json_url, Environment.DIRECTORY_DOWNLOADS, current_provider_item.name + "_provider.json"));
+ paths_to_downloaded_files.add(downloadProviderJSON("eip_service_json", current_provider_item.eip_service_json_url, Environment.DIRECTORY_DOWNLOADS, current_provider_item.name + "_eip-service.json"));
+
+ return paths_to_downloaded_files;
+ }
+
+ private String downloadProviderJSON(String type, String json_url, String target_directory, String filename) {
+
+ DownloadManager.Request request = new DownloadManager.Request(Uri.parse(json_url));
+ request.setDescription("Downloading JSON file");
+ request.setTitle("JSON file");
+ // in order for this if to run, you must use the android 3.2 to compile your app
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
+ request.allowScanningByMediaScanner();
+ request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
+ }
+ //request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, current_provider_item.name + "_provider.json");
+ request.setDestinationInExternalPublicDir(target_directory, filename);
+
+ // get download service and enqueue file
+ DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
+ manager.enqueue(request);
+ return type + ":" + target_directory + "/" + filename;
+
+ }
+}
diff --git a/src/se/leap/leapclient/ProviderListContent.java b/src/se/leap/leapclient/ProviderListContent.java
new file mode 100644
index 00000000..1fe60159
--- /dev/null
+++ b/src/se/leap/leapclient/ProviderListContent.java
@@ -0,0 +1,77 @@
+package se.leap.leapclient;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+
+public class ProviderListContent {
+
+ /**
+ * An array of sample (dummy) items.
+ */
+ public static List<ProviderItem> ITEMS = new ArrayList<ProviderItem>();
+
+ /**
+ * A map of sample (dummy) items, by ID.
+ */
+ public static Map<String, ProviderItem> ITEM_MAP = new HashMap<String, ProviderItem>();
+
+ static {
+ //addItem(new ProviderItem("1", "bitmask", "https://bitmask.net/provider.json", "https://api.bitmask.net:4430/1/config/eip-service.json"));
+ }
+
+ public static void addItem(ProviderItem item) {
+ ITEMS.add(item);
+ ITEM_MAP.put(String.valueOf(ITEMS.size()), item);
+ }
+
+ /**
+ * A dummy item representing a piece of content.
+ */
+ public static class ProviderItem {
+ public String id;
+ public String name;
+ public String provider_json_url;
+ public String eip_service_json_url;
+
+
+ public ProviderItem(String id, String name, String provider_json_url, String eip_service_json_url) {
+ this.id = id;
+ this.name = name;
+ this.provider_json_url = provider_json_url;
+ this.eip_service_json_url = eip_service_json_url;
+ }
+
+ public ProviderItem(String name, InputStream urls_file_input_stream) {
+
+ try {
+ byte[] urls_file_bytes = new byte[urls_file_input_stream.available()];
+ urls_file_input_stream.read(urls_file_bytes);
+ String urls_file_content = new String(urls_file_bytes);
+ JSONObject file_contents = new JSONObject(urls_file_content);
+ id = name;
+ this.name = name;
+ provider_json_url = (String) file_contents.get("json_provider");
+ eip_service_json_url = (String) file_contents.get("json_eip_service");
+ } catch (JSONException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+ }
+}
diff --git a/src/se/leap/leapclient/ProviderListFragment.java b/src/se/leap/leapclient/ProviderListFragment.java
new file mode 100644
index 00000000..717a65c1
--- /dev/null
+++ b/src/se/leap/leapclient/ProviderListFragment.java
@@ -0,0 +1,150 @@
+package se.leap.leapclient;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.support.v4.app.ListFragment;
+import android.view.View;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+
+import se.leap.leapclient.ProviderListContent;
+
+/**
+ * A list fragment representing a list of Providers. This fragment
+ * also supports tablet devices by allowing list items to be given an
+ * 'activated' state upon selection. This helps indicate which item is
+ * currently being viewed in a {@link DashboardFragment}.
+ * <p>
+ * Activities containing this fragment MUST implement the {@link Callbacks}
+ * interface.
+ */
+public class ProviderListFragment extends ListFragment {
+
+ /**
+ * The serialization (saved instance state) Bundle key representing the
+ * activated item position. Only used on tablets.
+ */
+ private static final String STATE_ACTIVATED_POSITION = "activated_position";
+
+ /**
+ * The fragment's current callback object, which is notified of list item
+ * clicks.
+ */
+ private Callbacks mCallbacks = sDummyCallbacks;
+
+ /**
+ * The current activated item position. Only used on tablets.
+ */
+ private int mActivatedPosition = ListView.INVALID_POSITION;
+
+ /**
+ * A callback interface that all activities containing this fragment must
+ * implement. This mechanism allows activities to be notified of item
+ * selections.
+ */
+ public interface Callbacks {
+ /**
+ * Callback for when an item has been selected.
+ */
+ public void onItemSelected(String id);
+ }
+
+ /**
+ * A dummy implementation of the {@link Callbacks} interface that does
+ * nothing. Used only when this fragment is not attached to an activity.
+ */
+ private static Callbacks sDummyCallbacks = new Callbacks() {
+ @Override
+ public void onItemSelected(String id) {
+ }
+ };
+
+ /**
+ * Mandatory empty constructor for the fragment manager to instantiate the
+ * fragment (e.g. upon screen orientation changes).
+ */
+ public ProviderListFragment() {
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setListAdapter(new ArrayAdapter<ProviderListContent.ProviderItem>(
+ getActivity(),
+ android.R.layout.simple_list_item_activated_1,
+ android.R.id.text1,
+ ProviderListContent.ITEMS));
+ }
+
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+
+ // Restore the previously serialized activated item position.
+ if (savedInstanceState != null
+ && savedInstanceState.containsKey(STATE_ACTIVATED_POSITION)) {
+ setActivatedPosition(savedInstanceState.getInt(STATE_ACTIVATED_POSITION));
+ }
+ }
+
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+
+ // Activities containing this fragment must implement its callbacks.
+ if (!(activity instanceof Callbacks)) {
+ throw new IllegalStateException("Activity must implement fragment's callbacks.");
+ }
+
+ mCallbacks = (Callbacks) activity;
+ }
+
+ @Override
+ public void onDetach() {
+ super.onDetach();
+
+ // Reset the active callbacks interface to the dummy implementation.
+ mCallbacks = sDummyCallbacks;
+ }
+
+ @Override
+ public void onListItemClick(ListView listView, View view, int position, long id) {
+ super.onListItemClick(listView, view, position, id);
+
+ // Notify the active callbacks interface (the activity, if the
+ // fragment is attached to one) that an item has been selected.
+ mCallbacks.onItemSelected(ProviderListContent.ITEMS.get(position).id);
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ if (mActivatedPosition != ListView.INVALID_POSITION) {
+ // Serialize and persist the activated item position.
+ outState.putInt(STATE_ACTIVATED_POSITION, mActivatedPosition);
+ }
+ }
+
+ /**
+ * Turns on activate-on-click mode. When this mode is on, list items will be
+ * given the 'activated' state when touched.
+ */
+ public void setActivateOnItemClick(boolean activateOnItemClick) {
+ // When setting CHOICE_MODE_SINGLE, ListView will automatically
+ // give items the 'activated' state when touched.
+ getListView().setChoiceMode(activateOnItemClick
+ ? ListView.CHOICE_MODE_SINGLE
+ : ListView.CHOICE_MODE_NONE);
+ }
+
+ private void setActivatedPosition(int position) {
+ if (position == ListView.INVALID_POSITION) {
+ getListView().setItemChecked(mActivatedPosition, false);
+ } else {
+ getListView().setItemChecked(position, true);
+ }
+
+ mActivatedPosition = position;
+ }
+}