Java tutorial
/******************************************************************************* * Copyright 2012 AndroidQuery (tinyeeliu@gmail.com) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Additional Note: * 1. You cannot use AndroidQuery's Facebook app account in your own apps. * 2. You cannot republish the app as is with advertisements. ******************************************************************************/ package com.androidquery.simplefeed.activity; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.json.JSONArray; import org.json.JSONObject; import android.app.Activity; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.ProgressDialog; import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.Bitmap.CompressFormat; import android.graphics.BitmapFactory; import android.graphics.BitmapFactory.Options; import android.location.Location; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.os.Environment; import android.provider.MediaStore; import android.text.TextUtils; import android.view.View; import android.view.inputmethod.InputMethodManager; import android.widget.ArrayAdapter; import android.widget.EditText; import android.widget.ImageView; import com.androidquery.AQuery; import com.androidquery.callback.AjaxCallback; import com.androidquery.callback.AjaxStatus; import com.androidquery.callback.BitmapAjaxCallback; import com.androidquery.simplefeed.R; import com.androidquery.simplefeed.base.Constants; import com.androidquery.simplefeed.base.MenuActivity; import com.androidquery.simplefeed.data.Entity; import com.androidquery.simplefeed.data.Entry; import com.androidquery.simplefeed.data.FeedItem; import com.androidquery.simplefeed.data.Place; import com.androidquery.simplefeed.util.AppUtility; import com.androidquery.simplefeed.util.FormatUtility; import com.androidquery.simplefeed.util.PrefUtility; import com.androidquery.util.AQUtility; public class PostActivity extends MenuActivity { private Entity entity; private FeedItem item; private File photo; private Bitmap bm; private Location location; private Place place; private List<Entity> tags; private String title; @Override protected void init(Bundle state) { Intent intent = getIntent(); String message = ""; photo = (File) intent.getSerializableExtra("photo"); message = intent.getStringExtra("message"); if (state != null) { if (photo == null) { photo = (File) state.getSerializable("photo"); } if (message == null) { message = state.getString("message"); } location = state.getParcelable("location"); place = (Place) state.getSerializable("place"); tags = (List<Entity>) state.getSerializable("tags"); } entity = (Entity) intent.getSerializableExtra("entity"); item = (FeedItem) intent.getSerializableExtra("item"); initView(message); albumCheck(0); } private void initView(String message) { aq.id(R.id.button_send).clicked(this, "sendClicked"); aq.id(R.id.button_photo).clicked(this, "photoClicked"); aq.id(R.id.button_checkin).clicked(this, "checkinClicked"); aq.id(R.id.button_gallery).clicked(this, "galleryClicked"); aq.id(R.id.button_tags).clicked(this, "tagsClicked"); aq.id(R.id.button_remove_image).clicked(this, "removePhotoClicked"); aq.id(R.id.button_remove_place).clicked(this, "removePlaceClicked"); aq.id(R.id.button_remove_tags).clicked(this, "removeTagsClicked"); String name = AppUtility.getUserName(); String name2 = null; String hint = getString(R.string.comment); if (item != null) { name2 = item.getFrom().getName(); disableAction(); } else if (entity != null) { String id = entity.getId(); if (id == null) { name2 = getString(R.string.wall); hint = getString(R.string.status_update); } else { name2 = entity.getName(); disableAction(); } } if (name2 == null) name2 = name; title = name + " > " + name2; updateTitle(System.currentTimeMillis()); attachPhoto(photo); attachPlace(place); attachFriends(tags); refreshButtons(); aq.id(R.id.edit_input).text(message).getTextView().setHint(hint); } private void disableAction() { aq.id(R.id.button_gallery).gone(); aq.id(R.id.button_photo).gone(); aq.id(R.id.button_checkin).gone(); aq.id(R.id.button_tags).gone(); } @Override protected int getContainerView() { return R.layout.activity_post; } public final static int REQUEST = 12; public static void start(Activity act, Entity entity) { Intent intent = new Intent(act, PostActivity.class); intent.putExtra("entity", entity); act.startActivityForResult(intent, REQUEST); } public static void start(Activity act, FeedItem item) { Intent intent = new Intent(act, PostActivity.class); intent.putExtra("item", item); act.startActivityForResult(intent, REQUEST); } public void tagsClicked(View view) { AQUtility.debug("tags clicked"); doneInput(); FriendsActivity.start(this, true); } public void sendClicked(View view) { String message = getMessage(); if (item != null) { AQUtility.debug(item.getObjectId()); //comment(item.getItemId(), message); comment(item.getActionId(), message); } else if (entity != null) { String id = entity.getId(); if (id == null) id = "me"; if (bm != null && photo != null) { photoPost(); } else if (location != null) { checkinPost(message, place, location); } else { wallPost(id, message); } } } private String getMessage() { String message = aq.id(R.id.edit_input).getEditable().toString(); return message; } private void checkinPost(String message, Place place, Location loc) { String url = "https://graph.facebook.com/me/checkins"; Map<String, Object> params = new HashMap<String, Object>(); params.put("message", message); putLocation(params, place, loc); putTags(params, tags); ProgressDialog dialog = makeProgressDialog(getString(R.string.sending)); aq.auth(handle).progress(dialog).ajax(url, params, JSONObject.class, this, "checkinCb"); //progressDialog(true, getString(R.string.sending)); } private void putTags(Map<String, Object> params, List<Entity> tags) { if (tags == null || tags.size() == 0) return; List<String> ids = new ArrayList<String>(); for (Entity tag : tags) { ids.add(tag.getId()); } String value = TextUtils.join(",", ids); AQUtility.debug("tags", value); params.put("tags", value); } private void putWallTags(Map<String, Object> params, List<Entity> tags) { if (tags == null || tags.size() == 0) return; } private void putPhotoTags(Map<String, Object> params, List<Entity> tags) { if (tags == null || tags.size() == 0) return; try { JSONArray ja = new JSONArray(); for (Entity tag : tags) { JSONObject jo = new JSONObject(); jo.putOpt("tag_uid", tag.getId()); jo.putOpt("x", 0); jo.putOpt("y", 0); ja.put(jo); } AQUtility.debug("tags", ja); params.put("tags", ja.toString()); } catch (Exception e) { AQUtility.report(e); } } private void putLocation(Map<String, Object> params, Place place, Location loc) { if (place == null || loc == null) return; try { JSONObject cord = new JSONObject(); cord.put("latitude", loc.getLatitude()); cord.put("longitude", loc.getLongitude()); params.put("place", place.getId()); params.put("coordinates", cord); } catch (Exception e) { AQUtility.report(e); } } public void checkinCb(String url, JSONObject jo, AjaxStatus status) { AQUtility.debug("checkin", jo); //progressDialog(false, ""); if (jo != null && jo.has("id")) { finish(R.string.done, true, null, getMessage()); } else if (status.getCode() == 403) { showToast(getString(R.string.no_permission)); } } private void wallPost(String id, String message) { String url = "https://graph.facebook.com/" + id + "/feed"; Map<String, Object> params = new HashMap<String, Object>(); params.put("message", message); putWallTags(params, tags); AQUtility.debug("wall", params); ProgressDialog dialog = makeProgressDialog(getString(R.string.sending)); aq.auth(handle).progress(dialog).ajax(url, params, JSONObject.class, this, "wallCb"); //progressDialog(true, getString(R.string.sending)); } public void wallCb(String url, JSONObject jo, AjaxStatus status) { //progressDialog(false, ""); AQUtility.debug(jo); if (jo != null && jo.has("id")) { finish(R.string.done, true, null, getMessage()); } else if (status.getCode() == 403) { showToast(getString(R.string.no_permission)); } } private void finish(int toast, boolean refresh, String itemId, String message) { doneInput(); Intent data = new Intent(); data.putExtra("toast", getString(toast)); data.putExtra("refresh", refresh); data.putExtra("itemId", itemId); data.putExtra("message", message); //setResult(RESULT_OK, data); aq.result(this, RESULT_OK, data); finish(); } private File makePhotoFile() { File result = null; try { String folder = Environment.getExternalStorageDirectory() + "/simplefb"; File file = new File(folder); file.mkdirs(); AQUtility.debug("file", file); result = new File(file, "photo.jpg"); } catch (Exception e) { AQUtility.report(e); } return result; } public void photoClicked(View view) { File file = makePhotoFile(); if (file == null) return; Uri outputFileUri = Uri.fromFile(file); Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri); startActivityForResult(intent, Constants.ACTIVITY_CAMERA); } protected boolean needProgress() { return false; } public void checkinClicked(View view) { AQUtility.debug("checkinClicked"); doneInput(); PlaceActivity.start(this); } @Override public void onSaveInstanceState(Bundle bundle) { bundle.putSerializable("photo", photo); bundle.putString("message", getMessage()); bundle.putParcelable("location", location); bundle.putSerializable("place", place); bundle.putSerializable("tags", (Serializable) tags); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { AQUtility.debug("p request", requestCode + ":" + resultCode); switch (requestCode) { case Constants.ACTIVITY_CAMERA: if (resultCode == RESULT_OK) { attachPhoto(makePhotoFile()); } break; case Constants.ACTIVITY_GALLERY: if (resultCode == RESULT_OK) { handleImage(data); } break; case Constants.ACTIVITY_CHECKIN: if (resultCode == RESULT_OK) { handleCheckin(data); } break; case Constants.ACTIVITY_FRIENDS: if (resultCode == RESULT_OK) { handleFriends(data); } break; default: super.onActivityResult(requestCode, resultCode, data); break; } } private void attachPhoto(File file) { if (file == null || !file.exists() || file.length() < 10) { aq.id(R.id.image_box).gone(); return; } AQUtility.debug("photo", file.length()); sendEnable(false); BitmapAjaxCallback cb = new BitmapAjaxCallback() { @Override protected void callback(String url, ImageView iv, Bitmap bm, AjaxStatus status) { sendEnable(true); if (photo != null && bm != null) { iv.setImageBitmap(bm); String dim = bm.getWidth() + "x" + bm.getHeight(); aq.id(R.id.text_dim).text(dim); String length = FormatUtility.scientificShort(photo.length()) + "b"; aq.id(R.id.text_size).text(length); PostActivity.this.bm = bm; } } }; cb.file(file).targetWidth(720);//.targetDim(false); aq.id(R.id.image_photo).image(cb); clear(); this.photo = file; refreshButtons(); } private void sendEnable(boolean enabled) { aq.id(R.id.button_send).enabled(enabled); } public void removePhotoClicked(View view) { aq.id(R.id.image_box).gone(); clear(); tags = null; refreshButtons(); } public void removePlaceClicked(View view) { aq.id(R.id.place_box).gone(); clear(); tags = null; refreshButtons(); } public void removeTagsClicked(View view) { aq.id(R.id.tags_box).gone(); tags = null; refreshButtons(); } @Override protected String makeTitle(long time) { if (title != null) { return title; } return super.makeTitle(time); } private byte[] toBytes(Bitmap bm) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); bm.compress(CompressFormat.JPEG, 90, baos); return baos.toByteArray(); } private Options getSize(File file) { BitmapFactory.Options options = null; options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeFile(file.getAbsolutePath(), options); return options; } public void galleryClicked(View view) { Intent intent = new Intent(); intent.setType("image/*"); intent.setAction(Intent.ACTION_GET_CONTENT); startActivityForResult(Intent.createChooser(intent, getString(R.string.photo)), Constants.ACTIVITY_GALLERY); } private void handleImage(Intent data) { Uri uri = data.getData(); String path = getImagePath(uri); if (path == null) { showToast(getString(R.string.no_sd)); return; } File file = new File(path); attachPhoto(file); } private void handleFriends(Intent data) { List<Entity> tags = (List<Entity>) data.getSerializableExtra("selected"); if (tags == null || tags.size() == 0) return; AQUtility.debug("friends", tags); this.tags = tags; attachFriends(tags); refreshButtons(); } private void attachFriends(List<Entity> tags) { if (tags != null && tags.size() > 0) { String meta = tags.get(0).getName(); if (tags.size() > 0) { meta += " (" + tags.size() + " " + getString(R.string.n_friends) + ")"; } aq.id(R.id.text_tags).text(meta); } } private void handleCheckin(Intent data) { Location loc = (Location) data.getParcelableExtra("location"); Place place = (Place) data.getSerializableExtra("place"); AQUtility.debug(loc, item); if (loc != null && place != null) { clear(); this.location = loc; this.place = place; attachPlace(place); refreshButtons(); } } private void attachPlace(Place place) { if (place != null) { aq.id(R.id.text_place).text(place.getName()); aq.id(R.id.image_place).image(place.getTb()); } } private void clear() { photo = null; bm = null; location = null; place = null; } private void refreshButtons() { if (photo != null) { aq.id(R.id.button_photo).enabled(true); aq.id(R.id.button_gallery).enabled(true); aq.id(R.id.button_checkin).enabled(false); aq.id(R.id.button_tags).enabled(true); aq.id(R.id.image_box).visible(); aq.id(R.id.place_box).gone(); } else if (place != null) { aq.id(R.id.button_photo).enabled(false); aq.id(R.id.button_gallery).enabled(false); aq.id(R.id.button_checkin).enabled(true); aq.id(R.id.button_tags).enabled(true); aq.id(R.id.image_box).gone(); aq.id(R.id.place_box).visible(); } else { aq.id(R.id.button_photo).enabled(true); aq.id(R.id.button_gallery).enabled(true); aq.id(R.id.button_checkin).enabled(true); aq.id(R.id.button_tags).enabled(false); aq.id(R.id.image_box).gone(); aq.id(R.id.place_box).gone(); } if (tags != null) { aq.id(R.id.tags_box).visible(); } else { aq.id(R.id.tags_box).gone(); } } private void doneInput() { EditText edit = aq.id(R.id.edit_input).getEditText(); InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(edit.getWindowToken(), 0); } private String getImagePath(Uri uri) { String[] projection = { MediaStore.Images.Media.DATA }; Cursor cursor = managedQuery(uri, projection, null, null, null); if (cursor == null) return null; int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); String path = null; if (cursor.moveToFirst()) { path = cursor.getString(column_index); } return path; } private void comment(String id, String message) { String url = "https://graph.facebook.com/" + id + "/comments"; //progressDialog(true, getString(R.string.sending)); Map<String, Object> params = new HashMap<String, Object>(); params.put("message", message); ProgressDialog dialog = makeProgressDialog(getString(R.string.sending)); aq.auth(handle).progress(dialog).ajax(url, params, JSONObject.class, this, "commentCb"); } public void commentCb(String url, JSONObject jo, AjaxStatus status) { //progressDialog(false, ""); AQUtility.debug(jo); if (jo != null && jo.has("id")) { finish(R.string.done, false, item.getId(), getMessage()); } else if (status.getCode() == 403) { showToast(getString(R.string.no_permission)); } } private void albumCheck(int expire) { String url = "https://graph.facebook.com/me/albums?locale=" + locale; AjaxCallback<JSONObject> cb = new AjaxCallback<JSONObject>(); cb.weakHandler(this, "albumCb"); aq.auth(handle).ajax(url, JSONObject.class, expire, cb); } public void albumCb(String url, JSONObject jo, AjaxStatus status) { AQUtility.debug(jo); List<Entry> albums = new ArrayList<Entry>(); albums.add(new Entry(getString(R.string.app_name), "me")); int position = 0; if (jo != null) { JSONArray ja = jo.optJSONArray("data"); for (int i = 0; i < ja.length(); i++) { JSONObject album = ja.optJSONObject(i); String name = album.optString("name"); String id = album.optString("id"); if ("mobile".equals(album.optString("type", "me"))) { position = i + 1; } albums.add(new Entry(name, id)); } if (status.expired(HALF_DAY)) { albumCheck(-1); } } ArrayAdapter<Entry> adapter = new ArrayAdapter<Entry>(this, android.R.layout.simple_spinner_item, albums); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); aq.id(R.id.spinner_album).adapter(adapter).setSelection(position).visible(); } private String getSelected() { String result = "me"; Entry entry = (Entry) aq.id(R.id.spinner_album).getSelectedItem(); if (entry != null) { result = entry.getValue(); } return result; } private void photoPost() { AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() { @Override protected Void doInBackground(Void... params) { try { String id = getSelected(); photoPost(id, getMessage(), photo); } catch (Exception e) { AQUtility.report(e); failed(); } return null; } }; task.execute(); finish(R.string.pending_upload, false, null, null); } private void photoPost(String id, String message, File file) { String url = "https://graph.facebook.com/" + id + "/photos"; Map<String, Object> params = new HashMap<String, Object>(); params.put("message", message); Options size = getSize(photo); if (bm.getWidth() == size.outWidth) { AQUtility.debug("use file"); params.put("source", file); } else { AQUtility.debug("use byte[]"); params.put("source", toBytes(bm)); } putLocation(params, place, location); putPhotoTags(params, tags); AQUtility.debug("params", params); AQuery aq = new AQuery(getApplicationContext()); aq.auth(handle).ajax(url, params, JSONObject.class, this, "photoCb"); } public void photoCb(String url, JSONObject jo, AjaxStatus status) { AQUtility.debug(jo); if (jo != null && jo.has("id")) { AQuery aq = new AQuery(getApplicationContext()); String url2 = "https://graph.facebook.com/" + jo.optString("id"); aq.auth(handle).ajax(url2, JSONObject.class, this, "photoDetailCb"); } else { failed(); } } public void photoDetailCb(String url, JSONObject jo, AjaxStatus status) { AQUtility.debug(jo); if (jo != null) { String tb = jo.optString("picture"); FeedItem item = new FeedItem(jo); uploaded(tb, item); } else { failed(); } } private void failed() { Intent intent = new Intent(this, PostActivity.class); intent.putExtra("photo", photo); intent.putExtra("message", getMessage()); intent.putExtra("entity", entity); intent.putExtra("item", item); AQUtility.debug("failed input", photo + ":" + getMessage()); AQUtility.debug("failed input2", intent.getSerializableExtra("photo") + ":" + intent.getStringExtra("message")); String failed = getString(R.string.upload_failed); notify(failed, getString(R.string.photo_upload), failed, intent); } private void uploaded(String tb, FeedItem item) { Intent notificationIntent = new Intent(this, ImageActivity.class); notificationIntent.putExtra("url", tb); notificationIntent.putExtra("item", item); notificationIntent.putExtra("album", false); String completed = getString(R.string.upload_completed); notify(completed, getString(R.string.photo_upload), completed, notificationIntent); } private void notify(String ticker, String title, String message, Intent intent) { String ns = Context.NOTIFICATION_SERVICE; NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns); int icon = R.drawable.launcher; long when = System.currentTimeMillis(); Notification notification = new Notification(icon, ticker, when); Context context = getApplicationContext(); CharSequence contentText = message; int id = getNotifyId(); PendingIntent contentIntent = PendingIntent.getActivity(this, id, intent, 0); notification.setLatestEventInfo(context, title, contentText, contentIntent); mNotificationManager.cancelAll(); AQUtility.debug("notify id", id); mNotificationManager.notify(id, notification); } private int getNotifyId() { long n = PrefUtility.getLong(Constants.PREF_NID, 1000L); n++; PrefUtility.put(Constants.PREF_NID, n); return (int) Math.abs(n % 10000); } }