Java tutorial
// This file is part of the Occyd Android Client // - an Android application for geolocation tagging // Copyright (C) 2008, Andrew Perry (ajperry@pansapiens.com) // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. package com.pansapiens.occyd; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.MalformedURLException; import java.net.URL; import java.net.URLEncoder; import org.json.JSONException; import org.json.JSONObject; import android.app.Activity; import android.app.Dialog; import android.app.ProgressDialog; import android.content.Intent; import android.location.Location; import android.location.LocationManager; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.TextView; import android.widget.Button; import android.widget.Toast; public class NewPost extends Activity { protected static final int DIALOG_POSTING = 0; LocationManager locationManager; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // start polling location ASAP, so it can be accurate by the time // the post button is pressed locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); LocationUpdater locupdater = new LocationUpdater(locationManager); locupdater.startUpdating(); setContentView(R.layout.newpost); final Button post_button = (Button) findViewById(R.id.post_button); post_button.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { String result_code = null; // get text from textboxes and encode it to be URL safe String desc = ((TextView) findViewById(R.id.desc_txt)).getText().toString(); String tags = ((TextView) findViewById(R.id.tags_txt)).getText().toString(); try { desc = URLEncoder.encode(desc, "UTF-8"); tags = URLEncoder.encode(tags, "UTF-8"); } catch (UnsupportedEncodingException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } // current API URL scheme uses commas between tags tags = tags.replace("+", ","); /* // turn space delimited tag list into a + delimited list, for the URL String[] tag_array = tags_txt.split(" "); String tags = null; for (int i = 0; i < tag_array.length; i++) { tags += tag_array[i]; if (i < tag_array.length-1) { tags += "+"; } } */ // TODO: put an accuracy check in here ... don't post if // the accuracy is too low ... // (or give a "really post with inaccurate location ?" warning) Location here = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); double lat = here.getLatitude(); double lon = here.getLongitude(); //Toast.makeText(NewPost.this, "Posting ...", // Toast.LENGTH_LONG).show(); try { String BASEURL = getString(R.string.occyd_server); String urlstr = String.format("%s/v1/posts/add?ll=%f,%f&desc=%s&tags=%s&link=%s", BASEURL, lat, lon, desc, tags, BASEURL); final URL url = new URL(urlstr); TextView tx = (TextView) findViewById(R.id.new_post_title); tx.setText(url.toString()); // run http fetch in a thread, with // 'posting' dialog final Thread tr = new Thread() { @Override public void run() { handle_result.post(mDisplayPosting); UrlFetch fetcher = new UrlFetch(url, handle_result); fetcher.fetch(); handle_result.post(mDismissPosting); } }; tr.start(); } catch (MalformedURLException e) { Toast.makeText(NewPost.this, "FAIL: Malformed URL.", Toast.LENGTH_LONG).show(); } catch (IOException e) { Toast.makeText(NewPost.this, "FAIL: http fetch failed.", Toast.LENGTH_LONG).show(); } } }); } // result handler - launches / kills // 'waiting' dialogs, recieves http result body final Handler handle_result = new Handler() { @Override public void handleMessage(Message msg) { //Toast.makeText(NewPost.this, msg.obj.toString(), // Toast.LENGTH_LONG).show(); try { String result_code = new JSONObject(msg.obj.toString()).getString("result"); if (result_code != null && result_code.equals("done")) { Toast.makeText(NewPost.this, "Sighting posted !!", Toast.LENGTH_LONG).show(); } else { Toast.makeText(NewPost.this, "FAIL: Posting failed :(", Toast.LENGTH_LONG).show(); } } catch (JSONException e) { Toast.makeText(NewPost.this, "FAIL: Malformed response from server.", Toast.LENGTH_LONG).show(); } } }; final Runnable mDisplayPosting = new Runnable() { public void run() { showDialog(DIALOG_POSTING); } }; final Runnable mDismissPosting = new Runnable() { public void run() { try { dismissDialog(DIALOG_POSTING); } catch (IllegalArgumentException e) { return; } } }; @Override protected Dialog onCreateDialog(int id) { switch (id) { case DIALOG_POSTING: { ProgressDialog dialog = new ProgressDialog(this); dialog.setTitle("Posting ..."); dialog.setMessage("Posting ..."); dialog.setIndeterminate(true); dialog.setCancelable(false); return dialog; } } return null; } @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); // group, id (for click handling), order, title int order = Menu.CATEGORY_CONTAINER + Menu.FLAG_ALWAYS_PERFORM_CLOSE; //menu.add(Menu.NONE, 0, order, "Search").setAlphabeticShortcut('s'); ; //menu.add(Menu.NONE, 1, order, "Post").setAlphabeticShortcut('p'); ; menu.add(Menu.NONE, 2, order, "Map").setAlphabeticShortcut('m'); menu.add(Menu.NONE, 3, order, "Settings"); menu.add(Menu.NONE, 4, order, "Help").setAlphabeticShortcut('h'); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { Intent I; switch (item.getItemId()) { case 0: I = new Intent(this, Search.class); break; case 1: I = new Intent(this, NewPost.class); break; case 2: // if we launch the map, leave this NewPost activity // on the history stack (ie no call of this.finish() ) // so that the back button brings us from the map back to here Toast.makeText(NewPost.this, "Finding location, mapping.", Toast.LENGTH_SHORT).show(); I = new Intent(this, MapResults.class); startActivity(I); return true; case 3: startActivity(new Intent(this, Prefs.class)); return true; case 4: //showAlert("Menu Item Clicked", "Help", "ok", null, false, null); return true; default: return false; } startActivity(I); this.finish(); return true; } }