aboutsummaryrefslogtreecommitdiffstats
path: root/main
diff options
context:
space:
mode:
Diffstat (limited to 'main')
-rw-r--r--main/res/layout/main.xml26
-rw-r--r--main/res/values/strings.xml10
-rw-r--r--main/src/cgeo/geocaching/cgeo.java71
-rw-r--r--main/src/cgeo/geocaching/cgeoapplication.java8
-rw-r--r--main/src/cgeo/geocaching/network/StatusUpdater.java75
5 files changed, 190 insertions, 0 deletions
diff --git a/main/res/layout/main.xml b/main/res/layout/main.xml
index 2f0b1d8..eedcc8a 100644
--- a/main/res/layout/main.xml
+++ b/main/res/layout/main.xml
@@ -17,6 +17,32 @@
android:src="@drawable/actionbar_manual"
android:onClick="goManual" />
</LinearLayout>
+ <RelativeLayout android:id="@+id/status"
+ android:visibility="gone"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentTop="true"
+ android:layout_marginLeft="16dip"
+ android:layout_marginRight="16dip"
+ android:layout_marginTop="60dip"
+ android:background="@drawable/helper_bcg" >
+ <ImageView android:id="@+id/status_icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_centerVertical="true"
+ android:layout_margin="4dip" />
+ <TextView android:id="@+id/status_message"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_toRightOf="@id/status_icon"
+ android:layout_centerVertical="true"
+ android:gravity="center"
+ android:padding="4dip"
+ android:textSize="14dip"
+ android:textColor="@color/text_icon" />
+ </RelativeLayout>
+<!-- ** -->
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
diff --git a/main/res/values/strings.xml b/main/res/values/strings.xml
index dcf4946..78b92db 100644
--- a/main/res/values/strings.xml
+++ b/main/res/values/strings.xml
@@ -978,6 +978,16 @@
<string name="about_auth_1">The following process allows <b>c:geo</b> to access Twitter - if agreed.</string>
<string name="about_auth_2">A click on the \"authorize c:geo\" button will start the process. This process will open up a web browser with a Twitter page. Login on this page and allow <b>c:geo</b> to access your account. If this is accepted, Twitter will show up a numeric PIN code. This PIN must be pasted into <b>c:geo</b> and confirmed. That\'s all.</string>
+ <!-- status -->
+ <string name="status_new_release">New release available.\nClick to install.</string>
+ <string name="status_new_nightly">New nightly build available.\nClick to install.</string>
+ <string name="status_new_rc">New release candidate available.\nClick to install.</string>
+ <string name="status_default_developer_build">You are running a developer build</string>
+ <string name="status_default_nightly">You are running a nightly build.\nPlease report issues.\n</string>
+ <string name="status_rc">You are running a release candidate.\nPlease report issues.\n"</string>
+ <string name="status_geocaching_change">Recent changes on geocaching.com broke c:geo.\nWe are working on it, check again soon.</string>
+ <string name="status_geocaching_livemap">Recent changes on geocaching.com broke the live map feature.\nWe are working on it, check again soon.</string>
+
<!-- go4cache -->
<string name="go4cache_looking_around">Looking around</string>
<string name="go4cache_tweeting">Tweeting</string>
diff --git a/main/src/cgeo/geocaching/cgeo.java b/main/src/cgeo/geocaching/cgeo.java
index f1535c5..a23e232 100644
--- a/main/src/cgeo/geocaching/cgeo.java
+++ b/main/src/cgeo/geocaching/cgeo.java
@@ -9,8 +9,11 @@ import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.geopoint.HumanDistance;
import cgeo.geocaching.geopoint.IConversion;
import cgeo.geocaching.maps.CGeoMap;
+import cgeo.geocaching.network.StatusUpdater;
+import cgeo.geocaching.network.StatusUpdater.Status;
import cgeo.geocaching.ui.Formatter;
import cgeo.geocaching.utils.GeoDirHandler;
+import cgeo.geocaching.utils.IObserver;
import cgeo.geocaching.utils.Log;
import cgeo.geocaching.utils.Version;
@@ -26,6 +29,7 @@ import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
import android.location.Address;
import android.location.Geocoder;
+import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
@@ -34,6 +38,8 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
@@ -173,6 +179,69 @@ public class cgeo extends AbstractActivity {
}
};
+ private class StatusHandler extends Handler implements IObserver<Status> {
+
+ @Override
+ public void update(final Status data) {
+ obtainMessage(0, data).sendToTarget();
+ }
+
+ @Override
+ public void handleMessage(final Message msg) {
+ final Status data = (Status) msg.obj;
+ updateDisplay(data != null && data.message != null ? data : StatusUpdater.defaultStatus());
+ }
+
+ private void updateDisplay(final Status data) {
+ final ViewGroup status = (ViewGroup) findViewById(R.id.status);
+ final ImageView statusIcon = (ImageView) findViewById(R.id.status_icon);
+ final TextView statusMessage = (TextView) findViewById(R.id.status_message);
+
+ if (data == null) {
+ status.setVisibility(View.GONE);
+ return;
+ }
+
+ if (data.icon != null) {
+ final int iconId = res.getIdentifier(data.icon, "drawable", getPackageName());
+ if (iconId != 0) {
+ statusIcon.setImageResource(iconId);
+ statusIcon.setVisibility(View.VISIBLE);
+ } else {
+ Log.e("StatusHandler: could not find icon corresponding to @drawable/" + data.icon);
+ statusIcon.setVisibility(View.GONE);
+ }
+ } else {
+ statusIcon.setVisibility(View.GONE);
+ }
+
+ String message = data.message;
+ if (data.messageId != null) {
+ final int messageId = res.getIdentifier(data.messageId, "string", getPackageName());
+ if (messageId != 0) {
+ message = res.getString(messageId);
+ }
+ }
+
+ statusMessage.setText(message);
+ status.setVisibility(View.VISIBLE);
+
+ if (data.url != null) {
+ status.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(final View v) {
+ startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(data.url)));
+ }
+ });
+ } else {
+ status.setClickable(false);
+ }
+ }
+
+ }
+
+ private StatusHandler statusHandler = new StatusHandler();
+
public cgeo() {
super("c:geo-main-screen");
}
@@ -224,6 +293,7 @@ public class cgeo extends AbstractActivity {
@Override
public void onResume() {
super.onResume();
+ app.getStatusUpdater().addObserver(statusHandler);
locationUpdater.startGeo();
satellitesHandler.startGeo();
updateUserInfoHandler.sendEmptyMessage(-1);
@@ -247,6 +317,7 @@ public class cgeo extends AbstractActivity {
@Override
public void onPause() {
initialized = false;
+ app.getStatusUpdater().deleteObserver(statusHandler);
locationUpdater.stopGeo();
satellitesHandler.stopGeo();
super.onPause();
diff --git a/main/src/cgeo/geocaching/cgeoapplication.java b/main/src/cgeo/geocaching/cgeoapplication.java
index 89ac250..66e3774 100644
--- a/main/src/cgeo/geocaching/cgeoapplication.java
+++ b/main/src/cgeo/geocaching/cgeoapplication.java
@@ -9,6 +9,7 @@ import cgeo.geocaching.enumerations.LoadFlags.SaveFlag;
import cgeo.geocaching.enumerations.LogType;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.geopoint.Viewport;
+import cgeo.geocaching.network.StatusUpdater;
import cgeo.geocaching.utils.IObserver;
import cgeo.geocaching.utils.Log;
@@ -40,11 +41,14 @@ public class cgeoapplication extends Application {
public boolean firstRun = true; // c:geo is just launched
public boolean showLoginToast = true; //login toast shown just once.
private boolean databaseCleaned = false; // database was cleaned
+ private StatusUpdater statusUpdater = null;
private static cgeoapplication instance = null;
public cgeoapplication() {
instance = this;
storage = new cgData(this);
+ statusUpdater = new StatusUpdater();
+ new Thread(statusUpdater).start();
}
public static cgeoapplication getInstance() {
@@ -193,6 +197,10 @@ public class cgeoapplication extends Application {
return dir;
}
+ public StatusUpdater getStatusUpdater() {
+ return statusUpdater;
+ }
+
public boolean storageStatus() {
return storage.status();
}
diff --git a/main/src/cgeo/geocaching/network/StatusUpdater.java b/main/src/cgeo/geocaching/network/StatusUpdater.java
new file mode 100644
index 0000000..c2e86f7
--- /dev/null
+++ b/main/src/cgeo/geocaching/network/StatusUpdater.java
@@ -0,0 +1,75 @@
+package cgeo.geocaching.network;
+
+import cgeo.geocaching.utils.MemorySubject;
+import cgeo.geocaching.utils.PeriodicHandler;
+import cgeo.geocaching.utils.Version;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import android.os.Looper;
+
+import java.util.Locale;
+
+public class StatusUpdater extends MemorySubject<StatusUpdater.Status> implements Runnable {
+
+ static public class Status {
+ final public String message;
+ final public String messageId;
+ final public String icon;
+ final public String url;
+
+ Status(final String message, final String messageId, final String icon, final String url) {
+ this.message = message;
+ this.messageId = messageId;
+ this.icon = icon;
+ this.url = url;
+ }
+ }
+
+ private void requestUpdate() {
+ final JSONObject response =
+ Network.requestJSON("http://status.cgeo.org/api/status.json",
+ new Parameters("version_code", "" + Version.getVersionCode(),
+ "version_name", Version.getVersionName(),
+ "locale", Locale.getDefault().toString()));
+ if (response != null) {
+ notifyObservers(new Status(get(response, "message"), get(response, "message_id"), get(response, "icon"), get(response, "url")));
+ }
+ }
+
+ private static String get(final JSONObject json, final String key) {
+ try {
+ return json.getString(key);
+ } catch (final JSONException e) {
+ return null;
+ }
+ }
+
+ @Override
+ public void run() {
+ notifyObservers(defaultStatus());
+ Looper.prepare();
+ new PeriodicHandler(1800000L) {
+ @Override
+ public void act() {
+ requestUpdate();
+ }
+ }.start();
+ Looper.loop();
+ }
+
+ public static Status defaultStatus() {
+ switch (Version.getVersionKind()) {
+ case RELEASE_CANDIDATE:
+ return new Status(null, "status_default_rc", null, null);
+ case NIGHTLY_BUILD:
+ return new Status(null, "status_default_nightly", null, null);
+ case DEVELOPER_BUILD:
+ return new Status(null, "status_default_developer_build", null, null);
+ default:
+ return null;
+ }
+ }
+
+}