Index: trunk/android-client/android-client.apk |
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Index: trunk/android-client/src/org/mediawiki/android/WikiPage.java |
— | — | @@ -1,5 +1,6 @@ |
2 | 2 | package org.mediawiki.android; |
3 | 3 | |
| 4 | +// Imports |
4 | 5 | import java.util.ArrayList; |
5 | 6 | import java.util.Hashtable; |
6 | 7 | import org.json.JSONArray; |
— | — | @@ -7,12 +8,15 @@ |
8 | 9 | import org.json.JSONObject; |
9 | 10 | import org.mediawiki.android.WikiApi; |
10 | 11 | |
| 12 | +// Class to handle the concept of a page in a Mediawiki install |
11 | 13 | public class WikiPage { |
12 | 14 | |
| 15 | + // Have we loaded the page |
13 | 16 | private boolean __loaded = false; |
| 17 | + |
| 18 | + // Our private instance of the WikiApi |
14 | 19 | private WikiApi __api; |
15 | 20 | |
16 | | - |
17 | 21 | // Aspects of the page |
18 | 22 | protected int __revId; |
19 | 23 | protected String __pageName; |
— | — | @@ -24,6 +28,10 @@ |
25 | 29 | protected ArrayList<String> __templates; |
26 | 30 | protected Hashtable<String,String> __interwikiLinks; |
27 | 31 | |
| 32 | + /** |
| 33 | + * Get the API |
| 34 | + * @return WikiApi |
| 35 | + */ |
28 | 36 | public WikiApi getApi() { |
29 | 37 | return this.__api; |
30 | 38 | } |
— | — | @@ -85,7 +93,8 @@ |
86 | 94 | } |
87 | 95 | |
88 | 96 | /** |
89 | | - * Load a new page |
| 97 | + * Load a new page from the current API |
| 98 | + * @param String page Page title to load |
90 | 99 | */ |
91 | 100 | public void loadPage( String page ) { |
92 | 101 | if ( this.__pageName == page ) { |
— | — | @@ -98,13 +107,17 @@ |
99 | 108 | |
100 | 109 | /** |
101 | 110 | * Have we loaded the data on this page? |
| 111 | + * @return boolean |
102 | 112 | */ |
103 | 113 | protected boolean isLoaded() { |
104 | 114 | return this.__loaded; |
105 | 115 | } |
106 | 116 | |
107 | 117 | /** |
108 | | - * |
| 118 | + * Load the page data. Functions needing data should call this, |
| 119 | + * as it handles (potentially) reading data from cache instead |
| 120 | + * of making remote requests. |
| 121 | + * @return boolean |
109 | 122 | */ |
110 | 123 | protected boolean loadData() { |
111 | 124 | if ( this.isLoaded() ) { |
— | — | @@ -119,11 +132,16 @@ |
120 | 133 | return this.__loaded; |
121 | 134 | } |
122 | 135 | |
| 136 | + /** |
| 137 | + * Couldn't find it in the cache, so make some remote calls to get |
| 138 | + * the information |
| 139 | + * @return boolean |
| 140 | + * @throws JSONException |
| 141 | + */ |
123 | 142 | protected boolean loadDataFromRemote() throws JSONException { |
124 | 143 | WikiApi api = this.getApi(); |
125 | 144 | api.newAction( "parse" ); |
126 | 145 | api.addParams( "prop", "revid|text|categories|externallinks|images|templates|links" ); |
127 | | - // api.addParams( "prop", "langlinks" ); |
128 | 146 | api.addParams( "page", this.__pageName ); |
129 | 147 | if ( api.doRequest() ) { |
130 | 148 | JSONObject json = api.getJson().getJSONObject( "parse" ); |
Index: trunk/android-client/src/org/mediawiki/android/HttpRequest.java |
— | — | @@ -1,5 +1,4 @@ |
2 | 2 | package org.mediawiki.android; |
3 | | - |
4 | 3 | // Imports |
5 | 4 | import java.io.IOException; |
6 | 5 | import java.net.SocketException; |
— | — | @@ -14,14 +13,19 @@ |
15 | 14 | import org.apache.http.impl.client.DefaultHttpClient; |
16 | 15 | |
17 | 16 | /** |
18 | | - * Class definition. Pretty simple use to get a raw HTTP GET/POST |
19 | | - * No caching, just a raw request. |
| 17 | + * Pretty simple use to get a raw HTTP GET/POST. No caching, just a raw request |
| 18 | + * Should remind MW devs of Http::get() and Http::post(). |
20 | 19 | */ |
21 | 20 | public class HttpRequest { |
22 | 21 | |
23 | 22 | // Keep a single client |
24 | 23 | private static HttpClient __client; |
25 | 24 | |
| 25 | + /** |
| 26 | + * Http GET request |
| 27 | + * @param String url URL to request |
| 28 | + * @return String |
| 29 | + */ |
26 | 30 | public static String get( String url ) { |
27 | 31 | URI uri = HttpRequest.makeUri( url ); |
28 | 32 | if ( uri == null ) { |
— | — | @@ -39,7 +43,12 @@ |
40 | 44 | } |
41 | 45 | return responseBody; |
42 | 46 | } |
43 | | - |
| 47 | + |
| 48 | + /** |
| 49 | + * Http POST request |
| 50 | + * @param String url URL to request |
| 51 | + * @return String |
| 52 | + */ |
44 | 53 | public static String post( String url ) { |
45 | 54 | URI uri = HttpRequest.makeUri( url ); |
46 | 55 | if ( uri == null ) { |
— | — | @@ -61,6 +70,10 @@ |
62 | 71 | return responseBody; |
63 | 72 | } |
64 | 73 | |
| 74 | + /** |
| 75 | + * Get the static instance of the HTTP client we keep around |
| 76 | + * @return HttpClient |
| 77 | + */ |
65 | 78 | private static HttpClient getClient() { |
66 | 79 | if ( HttpRequest.__client == null ) { |
67 | 80 | HttpRequest.__client = new DefaultHttpClient(); |
— | — | @@ -68,6 +81,11 @@ |
69 | 82 | return HttpRequest.__client; |
70 | 83 | } |
71 | 84 | |
| 85 | + /** |
| 86 | + * Friendly wrapper around making a URI object |
| 87 | + * @param String uri String URL to make into a URI object |
| 88 | + * @return URI |
| 89 | + */ |
72 | 90 | private static URI makeUri( String uri ) { |
73 | 91 | try { |
74 | 92 | return new URI( uri ); |
Index: trunk/android-client/src/org/mediawiki/android/WikiApi.java |
— | — | @@ -1,27 +1,42 @@ |
2 | 2 | package org.mediawiki.android; |
3 | 3 | |
| 4 | +// Imports |
4 | 5 | import org.json.JSONException; |
5 | 6 | import org.json.JSONObject; |
6 | 7 | import java.net.URLEncoder; |
7 | 8 | |
| 9 | +// Represents a single MW API somewhere in the universe |
8 | 10 | public class WikiApi { |
9 | 11 | |
| 12 | + // Always always always request JSON. |
10 | 13 | public static final String FORMAT = "json"; |
| 14 | + |
| 15 | + // Info about the wiki |
11 | 16 | private String __name; |
12 | 17 | private String __urlBase; |
| 18 | + |
| 19 | + // About our query |
13 | 20 | private String __lastJsonResult = null; |
14 | 21 | private String __action = "query"; // Default to action=query |
15 | 22 | private String __params = ""; |
16 | 23 | private String __fullRequestUrl; |
17 | 24 | private boolean __status = false; |
18 | 25 | private boolean __post = false; // set to true to be a posted request |
| 26 | + |
| 27 | + // We use a singleton() method, here's the instance |
19 | 28 | private static WikiApi __instance = null; |
20 | 29 | |
| 30 | + /** |
| 31 | + * Protect the constructor |
| 32 | + * @param apiName |
| 33 | + * @param apiUrl |
| 34 | + */ |
21 | 35 | protected WikiApi( String apiName, String apiUrl ) { |
22 | 36 | this.__name = apiName; |
23 | 37 | this.__urlBase = apiUrl; |
24 | 38 | } |
25 | 39 | |
| 40 | + /** Get singleton */ |
26 | 41 | public static WikiApi getSingleton() { |
27 | 42 | if ( WikiApi.__instance == null ) { |
28 | 43 | WikiApi.__instance = new WikiApi( "enwiki", "http://en.wikipedia.org/w/api.php" ); |
— | — | @@ -29,23 +44,42 @@ |
30 | 45 | return WikiApi.__instance; |
31 | 46 | } |
32 | 47 | |
| 48 | + /** Destroy singleton */ |
| 49 | + public void destroySingleton() { |
| 50 | + WikiApi.__instance = null; |
| 51 | + } |
| 52 | + |
| 53 | + /** Set a new action and void the parameters */ |
33 | 54 | public void newAction( String action ) { |
34 | 55 | this.__action = action; |
35 | 56 | this.__params = ""; |
36 | 57 | } |
37 | 58 | |
| 59 | + /** Get the name of this wiki */ |
38 | 60 | public String getName() { |
39 | 61 | return this.__name; |
40 | 62 | } |
41 | 63 | |
| 64 | + /** |
| 65 | + * Add some params to the request |
| 66 | + * @param String key Name of the param (prop, etc) |
| 67 | + * @param String value Value to set |
| 68 | + */ |
42 | 69 | public void addParams( String key, String value ) { |
43 | 70 | this.__params += "&" + key + "=" + URLEncoder.encode(value); |
44 | 71 | } |
45 | 72 | |
| 73 | + /** Should this be a post? */ |
46 | 74 | public void setPost( boolean p ) { |
47 | 75 | this.__post = p; |
48 | 76 | } |
49 | 77 | |
| 78 | + /** |
| 79 | + * Do the actual request. Note that we do some sanity checking |
| 80 | + * here, so we don't make the same request two times in a row. |
| 81 | + * @TODO Might want a way to allow that |
| 82 | + * @return boolean |
| 83 | + */ |
50 | 84 | public boolean doRequest() { |
51 | 85 | if ( this.__fullRequestUrl == this.getFullRequestUrl() ) { |
52 | 86 | return this.__status; |
— | — | @@ -66,15 +100,27 @@ |
67 | 101 | return this.__status; |
68 | 102 | } |
69 | 103 | |
| 104 | + /** |
| 105 | + * Construct the full query URL |
| 106 | + * @return String |
| 107 | + */ |
70 | 108 | public String getFullRequestUrl() { |
71 | 109 | return this.__urlBase + "?action=" + this.__action + |
72 | 110 | this.__params + "&format=" + WikiApi.FORMAT; |
73 | 111 | } |
74 | 112 | |
| 113 | + /** |
| 114 | + * Return the last JSON results raw |
| 115 | + * @return String |
| 116 | + */ |
75 | 117 | public String getRawResult() { |
76 | 118 | return this.__lastJsonResult; |
77 | 119 | } |
78 | 120 | |
| 121 | + /** |
| 122 | + * Get the last JSON results in a pretty wrapper |
| 123 | + * @return JSONObject |
| 124 | + */ |
79 | 125 | public JSONObject getJson() { |
80 | 126 | try { |
81 | 127 | return new JSONObject( this.__lastJsonResult ); |
Index: trunk/android-client/src/org/mediawiki/android/client/MainPage.java |
— | — | @@ -11,8 +11,10 @@ |
12 | 12 | import android.widget.EditText; |
13 | 13 | import android.widget.Toast; |
14 | 14 | |
| 15 | +// Entry point into MW client |
15 | 16 | public class MainPage extends Activity { |
16 | 17 | |
| 18 | + // Menu constants. We keep HOME public so other places can use it |
17 | 19 | public static final int HOME = 1; |
18 | 20 | private static final int ABOUT = 2; |
19 | 21 | private static final int CONFIG = 3; |
— | — | @@ -34,8 +36,7 @@ |
35 | 37 | startActivity( i ); |
36 | 38 | } |
37 | 39 | }; |
38 | | - |
39 | | - |
| 40 | + |
40 | 41 | /** Called when the activity is first created. */ |
41 | 42 | @Override |
42 | 43 | public void onCreate(Bundle savedInstanceState) { |
— | — | @@ -81,8 +82,7 @@ |
82 | 83 | } |
83 | 84 | |
84 | 85 | /** |
85 | | - * Simple helper function for making the "About" dialogue. Used |
86 | | - * on every page, so we'll just keep it here. |
| 86 | + * Simple helper function for making the "About" dialogue. |
87 | 87 | */ |
88 | 88 | private void constructAboutDialogue() { |
89 | 89 | String msg = getString(R.string.app_name) + "\nVersion " + |
Index: trunk/android-client/src/org/mediawiki/android/client/SearchPage.java |
— | — | @@ -1,15 +1,16 @@ |
2 | 2 | package org.mediawiki.android.client; |
3 | 3 | |
| 4 | +// Imports |
4 | 5 | import android.app.ListActivity; |
5 | 6 | import android.content.Intent; |
6 | 7 | import android.os.Bundle; |
| 8 | +import android.util.Log; |
7 | 9 | import android.view.Menu; |
8 | 10 | import android.view.MenuItem; |
9 | 11 | import android.view.View; |
10 | 12 | import android.widget.ArrayAdapter; |
11 | 13 | import android.widget.ListView; |
12 | 14 | import android.widget.Toast; |
13 | | - |
14 | 15 | import java.util.ArrayList; |
15 | 16 | import java.util.List; |
16 | 17 | import org.json.JSONArray; |
— | — | @@ -17,8 +18,14 @@ |
18 | 19 | import org.json.JSONObject; |
19 | 20 | import org.mediawiki.android.WikiApi; |
20 | 21 | |
| 22 | +// Class definition for a search results page |
21 | 23 | public class SearchPage extends ListActivity { |
22 | 24 | |
| 25 | + /** |
| 26 | + * Overriding the parent method. When the list item is clicked (in this |
| 27 | + * case, a search term), load up the ViewPage and let it show us the page |
| 28 | + * we've selected. |
| 29 | + */ |
23 | 30 | @Override |
24 | 31 | protected void onListItemClick(ListView l, View v, int position, long id) { |
25 | 32 | String title = (String)l.getItemAtPosition( position ); |
— | — | @@ -35,11 +42,15 @@ |
36 | 43 | try { |
37 | 44 | this.fillData( getIntent().getExtras().getString( "searchTerm" ) ); |
38 | 45 | } catch (JSONException e) { |
39 | | - Toast t = Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG ); |
40 | | - t.show(); |
| 46 | + Log.e( "JSON Error in Search", e.getMessage() ); |
41 | 47 | } |
42 | 48 | } |
43 | 49 | |
| 50 | + /** |
| 51 | + * Search for a term and fill ListActivity with the results |
| 52 | + * @param String searchTerm The term to look for in the API |
| 53 | + * @throws JSONException |
| 54 | + */ |
44 | 55 | private void fillData( String searchTerm ) throws JSONException { |
45 | 56 | List<String> items = new ArrayList<String>(); |
46 | 57 | WikiApi api = WikiApi.getSingleton(); |
— | — | @@ -63,7 +74,7 @@ |
64 | 75 | } |
65 | 76 | |
66 | 77 | /** |
67 | | - * Setup our menus at the bottom |
| 78 | + * Setup our menus at the bottom. Only linking to HOME here |
68 | 79 | */ |
69 | 80 | @Override |
70 | 81 | public boolean onCreateOptionsMenu( Menu menu ) { |
Index: trunk/android-client/src/org/mediawiki/android/client/ConfigurationPage.java |
— | — | @@ -1,8 +1,10 @@ |
2 | 2 | package org.mediawiki.android.client; |
3 | 3 | |
| 4 | +// Imports |
4 | 5 | import android.os.Bundle; |
5 | 6 | import android.preference.PreferenceActivity; |
6 | 7 | |
| 8 | +// Simple dummy activity for our preferences. Android manages 99% of this for us |
7 | 9 | public class ConfigurationPage extends PreferenceActivity { |
8 | 10 | |
9 | 11 | /** Called when the activity is first created. */ |
Index: trunk/android-client/src/org/mediawiki/android/client/ViewPage.java |
— | — | @@ -1,8 +1,8 @@ |
2 | 2 | package org.mediawiki.android.client; |
3 | 3 | |
| 4 | +// Imports |
4 | 5 | import org.mediawiki.android.WikiApi; |
5 | 6 | import org.mediawiki.android.WikiPage; |
6 | | - |
7 | 7 | import android.app.Activity; |
8 | 8 | import android.content.Intent; |
9 | 9 | import android.os.Bundle; |
— | — | @@ -11,6 +11,7 @@ |
12 | 12 | import android.view.MenuItem; |
13 | 13 | import android.widget.TextView; |
14 | 14 | |
| 15 | +// Base class definition for viewing pages |
15 | 16 | public class ViewPage extends Activity { |
16 | 17 | |
17 | 18 | protected static final int PAGELINKS = 2; |
— | — | @@ -41,6 +42,7 @@ |
42 | 43 | view.setText( Html.fromHtml(html) ); |
43 | 44 | } |
44 | 45 | |
| 46 | + /** Accessor method for setting our page title. */ |
45 | 47 | private void makePageTitle() { |
46 | 48 | this.setTitle( this.getTitle() + " - " + this.pageTitle ); |
47 | 49 | } |
Index: trunk/android-client/README |
— | — | @@ -15,14 +15,13 @@ |
16 | 16 | * Makes request to API url entered, Returns some default information on page |
17 | 17 | name provided. |
18 | 18 | |
19 | | -TODO: |
| 19 | +TODO (in no real order): |
20 | 20 | 1) i18n - check Google's progress in native Android. Possible workarounds? |
21 | | - 2) Document everything |
22 | | - 3) Make the cache work |
23 | | - 4) Multiple wiki sources in prefs |
24 | | - 5) User authentication |
25 | | - 6) Make data available as a ContentProvider |
26 | | - 7) Make page views actually attractive and usable (not just POC) |
| 21 | + 2) Make the cache work |
| 22 | + 3) Multiple wiki sources in prefs |
| 23 | + 4) User authentication |
| 24 | + 5) Make data available as a ContentProvider |
| 25 | + 6) Make page views actually attractive and usable (not just POC) |
27 | 26 | |
28 | 27 | -- |
29 | 28 | This program is free software; you can redistribute it and/or modify |