android-ibc-forum

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

commit 8cdb28800844b6c9b6121a9133314ea3a3002d1c
parent ea76782d864754b1c637cd177787559ebfcdeb35
Author: Jan Dankert <devnull@localhost>
Date:   Wed, 25 Jan 2012 02:07:54 +0100

Suchfunktion integriert.

Diffstat:
AndroidManifest.xml | 26+++++++++++++++++++-------
res/values/ibc.xml | 2+-
res/values/strings.xml | 2++
res/xml/searchable.xml | 5+++++
src/de/mtbnews/android/ForumActivity.java | 7++++---
src/de/mtbnews/android/MailboxActivity.java | 2--
src/de/mtbnews/android/MessageActivity.java | 58++++++++++++++++++++++++++++++++++++++++++----------------
src/de/mtbnews/android/SearchActivity.java | 195+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/de/mtbnews/android/adapter/MapContentAdapter.java | 5++++-
src/de/mtbnews/android/tapatalk/TapatalkClient.java | 176++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------
src/de/mtbnews/android/tapatalk/wrapper/Search.java | 34++++++++++++++++++++++++++++++++++
src/de/mtbnews/android/tapatalk/wrapper/Topic.java | 86+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/de/mtbnews/android/util/AppData.java | 9+++++++++
src/de/mtbnews/android/util/ServerAsyncTask.java | 6+++---
src/org/xmlrpc/android/XMLRPCClient.java | 12++++++++++++
15 files changed, 572 insertions(+), 53 deletions(-)

diff --git a/AndroidManifest.xml b/AndroidManifest.xml @@ -1,9 +1,9 @@ <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" - android:versionCode="1" - android:versionName="1.0" package="de.mtbnews.android"> + android:versionCode="1" android:versionName="1.0" package="de.mtbnews.android"> - <application android:icon="@drawable/ibc_icon" android:label="@string/app_name" android:theme="@style/IBC"> + <application android:icon="@drawable/ibc_icon" + android:label="@string/app_name" android:theme="@style/IBC"> <activity android:name=".IBCActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> @@ -15,19 +15,31 @@ <activity android:name="NewsDetailActivity" android:label="@string/news"></activity> <activity android:name="PhotoActivity" android:label="@string/photos"></activity> - + <activity android:name="ForumOverviewActivity" android:label="@string/forum"></activity> <activity android:name="ForumActivity" android:label="@string/forum"></activity> <activity android:name="TopicActivity" android:label="@string/forum"></activity> <activity android:name="PostActivity" android:label="@string/forum"></activity> - + + <activity android:name=".SearchActivity"> + <intent-filter> + <action android:name="android.intent.action.SEARCH" /> + </intent-filter> + <meta-data android:name="android.app.searchable" + android:resource="@xml/searchable" /> + </activity> + <activity android:name="MailboxActivity" android:label="@string/news"></activity> <activity android:name="MailActivity" android:label="@string/news"></activity> <activity android:name="MessageActivity" android:label="@string/news"></activity> + <!-- declare the default searchable Activity for the whole app --> + <meta-data android:name="android.app.default_searchable" + android:value=".SearchActivity" /> + <service android:name=".service.UploadIntentService"></service> - -</application> + + </application> <uses-permission android:name="android.permission.INTERNET" /> diff --git a/res/values/ibc.xml b/res/values/ibc.xml @@ -33,7 +33,7 @@ <style name="normalText"> <item name="android:background">#E3E3E3</item> - <item name="android:textSize">13sp</item> + <item name="android:textSize">14sp</item> <item name="android:textColor">#000000</item> </style> <style name="titleText"> diff --git a/res/values/strings.xml b/res/values/strings.xml @@ -3,6 +3,7 @@ <string name="sub_only">Forum enthält keine Themen</string> <string name="app_name">IBC</string> + <string name="search_for_topics">Suche nach Themen</string> <string name="preferences">Einstellungen</string> <string name="username">Benutzername</string> <string name="path">Pfad</string> @@ -34,6 +35,7 @@ <string name="waitingfor_news">Neue Nachrichten werden geladen</string> <string name="waitingfor_forum">Foren werden geladen</string> <string name="waitingfor_topic">Thema wird geladen</string> + <string name="waitingfor_search">Suche läuft</string> <string name="waitingforcontent">Inhalt wird geladen</string> <string name="waitingforprojects">Projekte werden geladen</string> <string name="waitingfor_login">Anmeldung am Server</string> diff --git a/res/xml/searchable.xml b/res/xml/searchable.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<searchable xmlns:android="http://schemas.android.com/apk/res/android" + android:label="@string/app_name" android:hint="@string/search_for_topics" android:includeInGlobalSearch="false"> +</searchable>+ \ No newline at end of file diff --git a/src/de/mtbnews/android/ForumActivity.java b/src/de/mtbnews/android/ForumActivity.java @@ -49,8 +49,7 @@ public class ForumActivity extends ListActivity @Override protected void onCreate(Bundle savedInstanceState) { - if (AppData.client == null) - AppData.client = new TapatalkClient(IBC.IBC_FORUM_CONNECTOR_URL); + super.onCreate(savedInstanceState); @@ -58,7 +57,9 @@ public class ForumActivity extends ListActivity prefs = PreferenceManager.getDefaultSharedPreferences(this); - if (!AppData.client.loggedIn && prefs.getBoolean("auto_login", false)) + TapatalkClient client = AppData.getTapatalkClient(); + + if (!client.loggedIn && prefs.getBoolean("auto_login", false)) { login(); } diff --git a/src/de/mtbnews/android/MailboxActivity.java b/src/de/mtbnews/android/MailboxActivity.java @@ -36,8 +36,6 @@ public class MailboxActivity extends ListActivity super.onCreate(savedInstanceState); - super.onCreate(savedInstanceState); - setContentView(R.layout.listing); new ServerAsyncTask(this, R.string.waitingforcontent) diff --git a/src/de/mtbnews/android/MessageActivity.java b/src/de/mtbnews/android/MessageActivity.java @@ -9,9 +9,19 @@ import org.mcsoxford.rss.RSSReader; import org.mcsoxford.rss.RSSReaderException; import android.app.Activity; +import android.content.Intent; import android.os.Bundle; +import android.text.Html; +import android.text.format.DateFormat; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; import android.widget.ListAdapter; +import android.widget.TextView; +import de.mtbnews.android.NewsDetailActivity.ImageGetter; import de.mtbnews.android.adapter.RSSContentAdapter; +import de.mtbnews.android.tapatalk.TapatalkClient; +import de.mtbnews.android.util.AppData; import de.mtbnews.android.util.IBC; import de.mtbnews.android.util.ServerAsyncTask; @@ -20,35 +30,51 @@ public class MessageActivity extends Activity @Override protected void onCreate(Bundle savedInstanceState) { - setContentView(R.layout.listing); + setContentView(R.layout.newsdetail); super.onCreate(savedInstanceState); new ServerAsyncTask(this, R.string.waitingforcontent) { - - private RSSFeed feed; + private TapatalkClient client; @Override protected void callServer() throws IOException { - RSSReader reader = new RSSReader(); - try - { - feed = reader.load(IBC.IBC_NEWS_RSS_URL); - } - catch (RSSReaderException e) - { - throw new ClientProtocolException(e); - } + client = AppData.getTapatalkClient(); } protected void doOnSuccess() { - ListAdapter adapter = new RSSContentAdapter( - MessageActivity.this, feed); - MessageActivity.this.setTitle(feed.getTitle()); - // setListAdapter(adapter); + // MessageActivity.this.setTitle(feed.getTitle()); + + TextView datum = (TextView) findViewById(R.id.item_date); + // datum.setText(DateFormat.getTimeFormat(this).format(item.getPubDate())); + + // TextView name = (TextView) findViewById(R.id.item_title); + // name.setText(item.getTitle()); + + final TextView desc = (TextView) findViewById(R.id.item_description); + + // if (e.getContent() != null) + // final String html = item.getContent(); + // desc.setText(Html.fromHtml(html, new ImageGetter(), null)); + // setTitle(item.getTitle()); + + Button button = (Button) findViewById(R.id.item_button); + button.setOnClickListener(new OnClickListener() + { + + @Override + public void onClick(View v) + + { + Intent i = new Intent(Intent.ACTION_VIEW); + // i.setData(item.getLink()); + startActivity(i); + } + }); + } }.execute(); diff --git a/src/de/mtbnews/android/SearchActivity.java b/src/de/mtbnews/android/SearchActivity.java @@ -0,0 +1,195 @@ +/** + * + */ +package de.mtbnews.android; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import android.app.ListActivity; +import android.app.SearchManager; +import android.content.Intent; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.util.Log; +import android.view.View; +import android.widget.AbsListView; +import android.widget.AdapterView; +import android.widget.BaseAdapter; +import android.widget.ListAdapter; +import android.widget.ListView; +import android.widget.AbsListView.OnScrollListener; +import android.widget.AdapterView.OnItemClickListener; +import de.mtbnews.android.adapter.ListEntryContentAdapter; +import de.mtbnews.android.tapatalk.TapatalkClient; +import de.mtbnews.android.tapatalk.TapatalkException; +import de.mtbnews.android.tapatalk.wrapper.Search; +import de.mtbnews.android.tapatalk.wrapper.Topic; +import de.mtbnews.android.util.AppData; +import de.mtbnews.android.util.ServerAsyncTask; + +/** + * @author dankert + * + */ +public class SearchActivity extends ListActivity +{ + public static final String ID = "id"; + public static final String CLIENT = "client"; + + private boolean loadingMore = true; + + private int displayFrom; + private int displayTo; + private int postCount; + + private List<Topic> topics; + private Search search; + + Map<String, String> data; + private String query; + + @Override + protected void onCreate(Bundle savedInstanceState) + { + final SharedPreferences prefs = PreferenceManager + .getDefaultSharedPreferences(this); + + super.onCreate(savedInstanceState); + setContentView(R.layout.listing); + + Intent intent = getIntent(); + + if (Intent.ACTION_SEARCH.equals(intent.getAction())) + { + query = intent.getStringExtra(SearchManager.QUERY); + } + + Log.d("IBC", "Searching for '" + query + "'"); + + new ServerAsyncTask(this, R.string.waitingfor_search) + { + + @Override + protected void callServer() throws IOException + { + TapatalkClient client = AppData.getTapatalkClient(); + + try + { + int start = 0; + int end = Integer.parseInt(prefs + .getString("num_load", "10")) - 1; + + displayFrom = start; + displayTo = end; + + search = client.searchTopics(query, start, end, null); + + postCount = search.topicCount; + topics = search.getTopics(); + + loadingMore = false; + } + catch (TapatalkException e) + { + throw new RuntimeException(e); + } + } + + protected void doOnSuccess() + { + SearchActivity.this.setTitle(query); + ListAdapter adapter = new ListEntryContentAdapter( + SearchActivity.this, topics); + setListAdapter(adapter); + + } + + }.execute(); + final ListView list = getListView(); + + list.setOnItemClickListener(new OnItemClickListener() + { + @Override + public void onItemClick(AdapterView<?> parent, View view, + int position, long id) + { + final Intent intent = new Intent(SearchActivity.this, + TopicActivity.class); + Topic topic = topics.get(position); + intent.putExtra("topic_id", topic.getId()); + startActivity(intent); + } + }); + + /** + * Weitere List-Einträge automatisch nachladen. + */ + list.setOnScrollListener(new OnScrollListener() + { + + @Override + public void onScrollStateChanged(AbsListView view, int scrollState) + { + } + + @Override + public void onScroll(AbsListView view, int firstVisibleItem, + int visibleItemCount, int totalItemCount) + { + + // what is the bottom iten that is visible + int lastInScreen = firstVisibleItem + visibleItemCount; + + // is the bottom item visible & not loading more already ? Load + // more ! + if ((lastInScreen == totalItemCount) && !(loadingMore) + /*&& !(totalItemCount >= search.topicCount)*/) + { + loadingMore = true; + new ServerAsyncTask(SearchActivity.this, + R.string.waitingfor_loadmore) + { + @Override + protected void callServer() throws IOException + { + TapatalkClient client = AppData.client; + + try + { + int start = displayTo + 1; + int end = start + + Integer.parseInt(prefs.getString( + "num_load", "10")) - 1; + displayTo = end; + + search = client.searchTopics(null, start, end, + search.searchId); + + topics.addAll(search.getTopics()); + + loadingMore = false; + } + catch (TapatalkException e) + { + throw new RuntimeException(e); + } + } + + protected void doOnSuccess() + { + ((BaseAdapter) getListAdapter()) + .notifyDataSetChanged(); + } + + }.execute(); + + } + } + }); + + } +} diff --git a/src/de/mtbnews/android/adapter/MapContentAdapter.java b/src/de/mtbnews/android/adapter/MapContentAdapter.java @@ -7,6 +7,7 @@ import java.util.List; import java.util.Map; import android.content.Context; +import android.opengl.Visibility; import android.text.format.DateFormat; import android.view.LayoutInflater; import android.view.View; @@ -116,7 +117,7 @@ public class MapContentAdapter extends BaseAdapter } else { - viewHolder.datum.setEnabled(false); + viewHolder.datum.setVisibility(View.INVISIBLE); } if (titleKey != null) @@ -131,6 +132,8 @@ public class MapContentAdapter extends BaseAdapter viewHolder.desc.setText(new String((byte[]) e.get(descriptionKey))); else viewHolder.desc.setText(""); + } else { + viewHolder.desc.setText(""); } return convertView; diff --git a/src/de/mtbnews/android/tapatalk/TapatalkClient.java b/src/de/mtbnews/android/tapatalk/TapatalkClient.java @@ -8,8 +8,11 @@ import java.util.Map; import org.xmlrpc.android.XMLRPCClient; import org.xmlrpc.android.XMLRPCException; +import android.util.Log; + import de.mtbnews.android.tapatalk.wrapper.Forum; import de.mtbnews.android.tapatalk.wrapper.Post; +import de.mtbnews.android.tapatalk.wrapper.Search; import de.mtbnews.android.tapatalk.wrapper.Topic; /** @@ -32,6 +35,19 @@ public class TapatalkClient public Map<String, Object> login(String username, String password) throws TapatalkException { + try + { + + final Map<String, Object> map = (Map<String, Object>) toMap(getXMLRPCClient() + .call("get_config")); + Log.i("IBC Server Config", map.toString()); + for (String key : map.keySet()) + Log.d("IBC Server Config", key + "=" + map.get(key)); + } + catch (XMLRPCException e) + { + throw new TapatalkException("Load Config failed", e); + } final Object[] params = new Object[] { username.getBytes(), password.getBytes() }; @@ -48,6 +64,7 @@ public class TapatalkClient { throw new TapatalkException("Login failed", e); } + } public void logout() throws TapatalkException @@ -101,26 +118,6 @@ public class TapatalkClient } } - private Map toMap(Object o) throws TapatalkException - { - if (!(o instanceof Map)) - { - throw new TapatalkException("no map: " + o.toString() + " (" - + o.getClass() + ")"); - } - Map map = (Map) o; - - Object object = map.get("result"); - if (object == null) - return map; - - boolean ok = (Boolean) object; - if (!ok) - throw new TapatalkException(byteArrayToString(map - .get("result_text"))); - return map; - } - @SuppressWarnings("unchecked") public Forum getForum(String forumId) throws TapatalkException { @@ -156,6 +153,124 @@ public class TapatalkClient } } + public Search searchTopics(String query, int start, int end, String searchId) + throws TapatalkException + { + try + { + final Object[] params; + + if (searchId == null) + params = new Object[] { query.getBytes(), start, end }; + else + params = new Object[] { "".getBytes(), start, end, searchId }; + + Map map = toMap(client.callEx("search_topic", params)); + + Integer topicCount = (Integer) map.get("total_topic_num"); + String newSearchId = (String) map.get("search_id"); + final List<Topic> topics = new ArrayList<Topic>(); + Search search = new Search(topicCount, newSearchId, topics); + + final List<Post> posts = new ArrayList<Post>(); + + for (Object o1 : (Object[]) map.get("topics")) + { + Map topicMap = toMap(o1); + Topic topic = new Topic((String) topicMap.get("topic_id"), + posts, // + byteArrayToString(topicMap.get("topic_title")),// + (Date) topicMap.get("post_time"), // + new String((byte[]) topicMap.get("short_content")),// + 0); + topics.add(topic); + } + + return search; + } + catch (XMLRPCException e) + { + throw new TapatalkException("Could not search", e); + } + } + + public Search getBoxContent(String boxId, int start, int end) + throws TapatalkException + { + try + { + final Object[] params = new Object[] { boxId, start, end }; + + Map map = toMap(client.callEx("get_box", params)); + + Integer topicCount = (Integer) map.get("total_topic_num"); + String newSearchId = (String) map.get("search_id"); + final List<Topic> topics = new ArrayList<Topic>(); + Search search = new Search(topicCount, newSearchId, topics); + + final List<Post> posts = new ArrayList<Post>(); + + for (Object o1 : (Object[]) map.get("topics")) + { + Map topicMap = toMap(o1); + Topic topic = new Topic((String) topicMap.get("topic_id"), + posts, // + byteArrayToString(topicMap.get("topic_title")),// + (Date) topicMap.get("post_time"), // + new String((byte[]) topicMap.get("short_content")),// + 0); + topics.add(topic); + } + + return search; + } + catch (XMLRPCException e) + { + throw new TapatalkException("Could not search", e); + } + } + + public Search getMessage(String query, int start, int end, String searchId) + throws TapatalkException + { + try + { + final Object[] params; + + if (searchId == null) + params = new Object[] { query.getBytes(), start, end }; + else + params = new Object[] { "".getBytes(), start, end, searchId }; + + Map map = toMap(client.callEx("search_topic", params)); + + Integer topicCount = (Integer) map.get("total_topic_num"); + String newSearchId = (String) map.get("search_id"); + final List<Topic> topics = new ArrayList<Topic>(); + Search search = new Search(topicCount, newSearchId, topics); + + final List<Post> posts = new ArrayList<Post>(); + + for (Object o1 : (Object[]) map.get("topics")) + { + Map topicMap = toMap(o1); + Topic topic = new Topic((String) topicMap.get("topic_id"), + posts, // + byteArrayToString(topicMap.get("topic_title")),// + (Date) topicMap.get("post_time"), // + new String((byte[]) topicMap.get("short_content")),// + 0); + topics.add(topic); + } + + return search; + } + catch (XMLRPCException e) + { + throw new TapatalkException("Could not search", e); + } + } + public XMLRPCClient getXMLRPCClient() { return client; @@ -178,4 +293,25 @@ public class TapatalkClient else return i.intValue(); } + + private Map toMap(Object o) throws TapatalkException + { + if (!(o instanceof Map)) + { + throw new TapatalkException("no map: " + o.toString() + " (" + + o.getClass() + ")"); + } + Map map = (Map) o; + + Object object = map.get("result"); + if (object == null) + return map; + + boolean ok = (Boolean) object; + if (!ok) + throw new TapatalkException(byteArrayToString(map + .get("result_text"))); + return map; + } + } diff --git a/src/de/mtbnews/android/tapatalk/wrapper/Search.java b/src/de/mtbnews/android/tapatalk/wrapper/Search.java @@ -0,0 +1,34 @@ +package de.mtbnews.android.tapatalk.wrapper; + +import java.util.List; + +public class Search +{ + + public int topicCount; + public String searchId; + + private List<Topic> topics; + + /** + * @param topicCount + * @param searchId + * @param topics + */ + public Search(int topicCount, String searchId, List<Topic> topics) + { + super(); + this.topicCount = topicCount; + this.searchId = searchId; + this.topics = topics; + } + + /** + * @return the topics + */ + public List<Topic> getTopics() + { + return topics; + } + +} diff --git a/src/de/mtbnews/android/tapatalk/wrapper/Topic.java b/src/de/mtbnews/android/tapatalk/wrapper/Topic.java @@ -0,0 +1,86 @@ +package de.mtbnews.android.tapatalk.wrapper; + +import java.util.Date; +import java.util.List; + +public class Topic implements ListEntry +{ + + private String id; + + private List<Post> posts; + + private String title; + private Date date; + private String content; + private int postCount; + + /** + * @param id + * @param posts + * @param title + * @param date + * @param content + * @param postCount + */ + public Topic(String id, List<Post> posts, String title, Date date, + String content, int postCount) + { + super(); + this.id = id; + this.posts = posts; + this.title = title; + this.date = date; + this.content = content; + this.postCount = postCount; + } + + /** + * @return the postCount + */ + public int getPostCount() + { + return postCount; + } + + /** + * @return the id + */ + public String getId() + { + return id; + } + + /** + * @return the title + */ + public String getTitle() + { + return title; + } + + /** + * @return the date + */ + public Date getDate() + { + return date; + } + + /** + * @return the content + */ + public String getContent() + { + return content; + } + + /** + * @return the posts + */ + public List<Post> getPosts() + { + return posts; + } + +} diff --git a/src/de/mtbnews/android/util/AppData.java b/src/de/mtbnews/android/util/AppData.java @@ -18,4 +18,13 @@ public class AppData public static RSSFeed photoFeed; public static TapatalkClient client; + + public static TapatalkClient getTapatalkClient() + { + + if (client == null) + AppData.client = new TapatalkClient(IBC.IBC_FORUM_CONNECTOR_URL); + + return client; + } } diff --git a/src/de/mtbnews/android/util/ServerAsyncTask.java b/src/de/mtbnews/android/util/ServerAsyncTask.java @@ -36,7 +36,7 @@ public abstract class ServerAsyncTask extends AsyncTask<Void, Void, Void> private ProgressDialog progressDialog; private Context context; private AlertDialog alertDialog; - private IOException error; + private Exception error; /** * @param context @@ -97,7 +97,7 @@ public abstract class ServerAsyncTask extends AsyncTask<Void, Void, Void> * @param error * Exception, die aufgetreten ist. */ - protected void doOnError(IOException error) + protected void doOnError(Exception error) { final Builder builder = new AlertDialog.Builder(this.context); alertDialog = builder.setCancelable(true).create(); @@ -140,7 +140,7 @@ public abstract class ServerAsyncTask extends AsyncTask<Void, Void, Void> { callServer(); } - catch (IOException e) + catch (Exception e) { Log.e(this.getClass().getName(), e.getMessage(), e); error = e; diff --git a/src/org/xmlrpc/android/XMLRPCClient.java b/src/org/xmlrpc/android/XMLRPCClient.java @@ -1,9 +1,12 @@ package org.xmlrpc.android; import java.io.BufferedInputStream; +import java.io.BufferedReader; import java.io.IOException; +import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; +import java.io.StringReader; import java.io.StringWriter; import java.net.URI; import java.net.URL; @@ -29,6 +32,8 @@ import org.apache.http.params.HttpProtocolParams; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserFactory; +import android.util.Log; + /** * XMLRPCClient allows to call remote XMLRPC method. * @@ -323,10 +328,17 @@ public class XMLRPCClient extends XMLRPCCommon { // lets start pulling... pullParser.nextTag(); + + //Log.d("XMLRPC response",this.inputStreamToString(entity.getContent())); + //entity.getContent().reset(); + pullParser.require(XmlPullParser.START_TAG, null, Tag.METHOD_RESPONSE); pullParser.nextTag(); // either Tag.PARAMS (<params>) or Tag.FAULT (<fault>) String tag = pullParser.getName(); + + Log.d("XMLRPC-Tag",tag); + if (tag.equals(Tag.PARAMS)) { // normal response pullParser.nextTag(); // Tag.PARAM (<param>)