/* * Copyright 2011 Adi Sayoga. * * 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. */ package com.adisayoga.earthquake.wrapper; import java.io.IOException; import java.net.URL; import java.util.List; import android.app.Activity; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.location.Address; import android.location.Geocoder; import android.location.Location; import android.os.Bundle; import android.os.Handler; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.widget.EditText; import android.widget.Toast; import com.adisayoga.earthquake.R; import com.adisayoga.earthquake.dto.EarthquakeDTO; import com.adisayoga.earthquake.dto.Unit; import com.adisayoga.earthquake.models.UsgsSource; import com.adisayoga.earthquake.utils.BaseRequestListener; import com.adisayoga.earthquake.utils.LocationUtils; import com.adisayoga.earthquake.utils.SessionEvents; import com.adisayoga.earthquake.utils.SessionEvents.AuthListener; import com.adisayoga.earthquake.utils.SessionEvents.LogoutListener; import com.adisayoga.earthquake.utils.SessionStore; import com.adisayoga.earthquake.utils.TimeUtils; import com.facebook.android.AsyncFacebookRunner; import com.facebook.android.DialogError; import com.facebook.android.Facebook; import com.facebook.android.Facebook.DialogListener; import com.facebook.android.FacebookError; /** * Class bantuan untuk memudahkan dalam berhubungan dengan Facebook. * * @author Adi Sayoga */ public class EarthquakeFacebook { public static final String TAG = "EarthquakeFacebook"; public static final String FACEBOOK_APP_ID = "239877329388468"; public static final String[] FACEBOOK_PERMISSION = new String[] { "publish_stream" }; private static Prefs prefs; private final Context context; private final Handler handler = new Handler(); private final Facebook facebook = new Facebook(FACEBOOK_APP_ID); private final SessionListener sessionListener = new SessionListener(); public EarthquakeFacebook(Context context) { this.context = context; prefs = Prefs.getInstance(context); SessionStore.restore(facebook, context); SessionEvents.addAuthListener(sessionListener); SessionEvents.addLogoutListener(sessionListener); } /** * Posting data gempa ke wall. Sebelumnya akan ditampilkan dialog apa yang * dipikirkan. * * @param activity Activity * @param quake Data gempa * @param location Lokasi saat ini */ public void postQuake(final Activity activity, final EarthquakeDTO quake, final Location location) { // Setup dialog LayoutInflater inflater = (LayoutInflater) activity.getSystemService( Context.LAYOUT_INFLATER_SERVICE); final View layout = inflater.inflate(R.layout.share_message, null); AlertDialog.Builder builder = new AlertDialog.Builder(activity); builder.setView(layout); builder.setTitle(R.string.share_to_facebook); builder.setPositiveButton(R.string.share, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { EditText messageText = (EditText) layout.findViewById(R.id.message); final String message = messageText.getText().toString(); new Thread() { @Override public void run() { // Generate parameter pada thread berbeda final Bundle params = genereateParams(quake, message, location); handler.post(new Runnable() { @Override public void run() { postMessageOrLogin(activity, params); } }); } }.start(); } }); builder.show(); } /** * Posting pesan ke wall, jika belum login dan activity tidak null maka akan * otomatis diarahkan untuk login, setelah itu baru pesan diposting. * * @param activity Activity * @param params Key-value string parameter */ public void postMessageOrLogin(Activity activity, final Bundle params) { if (facebook.isSessionValid()) { postMessageInThread(params); } else if (activity != null) { SessionEvents.AuthListener listener = new SessionEvents.AuthListener() { @Override public void onAuthSucceed() { postMessageInThread(params); } @Override public void onAuthFail(String error) { Toast.makeText(context, R.string.auth_fail, Toast.LENGTH_SHORT).show(); Log.w(TAG, error); } }; SessionEvents.addAuthListener(listener); login(activity); } else { handler.post(new Runnable() { @Override public void run() { Toast.makeText(context, R.string.post_fail, Toast.LENGTH_SHORT).show(); Log.d(TAG, "Belum login, tidak dapat login karena activity null"); } }); } } /** * Posting pesan ke wall (pada thread berbeda). * * @param params Key-value string parameter */ public void postMessageInThread(final Bundle params) { new Thread() { @Override public void run() { if (postMessage(params)) { handler.post(new Runnable() { @Override public void run() { Toast.makeText(context, R.string.post_sent, Toast.LENGTH_SHORT).show(); } }); } else { handler.post(new Runnable() { @Override public void run() { Toast.makeText(context, R.string.post_fail, Toast.LENGTH_SHORT).show(); } }); } } }.start(); } /** * Posting pesan ke wall. * * @param params Key-value string parameter * @return True jika posting berhasil, false jika gagal */ public boolean postMessage(Bundle params) { try { String response = facebook.request("me/feed", params, "POST"); Log.i(TAG, "Post sent: " + params.getString("description")); Log.d(TAG, "response: " + response); return true; } catch (IOException e) { Log.e(TAG, e.getMessage(), e); return false; } } /** * Menghasilkan parameter untuk diposting ke wall. * * @param quake Data gempa * @param message Pesan tambahan yang diinputkan user * @param location Lokasi saat ini * @param currentAddress Alamat lokasi saat ini * * @return Parameter */ public Bundle genereateParams(EarthquakeDTO quake, String message, Location location) { final Bundle params = new Bundle(); // message if (message != null && !message.equals("")) params.putString("message", message); // link params.putString("link", UsgsSource.getExternalUri(quake).toString()); // caption String date = TimeUtils.getInstance(context).toHumanReadable(quake.time); params.putString("caption", date); // picture URL pictureUrl = UsgsSource.getGlobeURL(quake); if (pictureUrl != null) params.putString("picture", pictureUrl.toString()); // description params.putString("description", generateDescription(quake, location)); return params; } /** * Men-generate description yaitu terdiri dari lokasi gempa, kedalaman gempa, * jarak user dengan gempa itu, dan alamat dimana user saat ini. * * @param quake Data gempa * @param location Lokasi user saat ini * @return String description */ private String generateDescription(EarthquakeDTO quake, Location location) { StringBuilder description = new StringBuilder(); Unit unit = prefs.getUnit(); // lokasi gempa String quakeLocation = LocationUtils.getInstance(context).formatLocation( quake.latitude, quake.longitude, true); description.append(context.getString(R.string.location)); description.append(" (").append(quakeLocation).append(")"); // kedalaman gempa String depth = unit.formatNumber(quake.depth, EarthquakeDTO .FRACTION_DEPTH); description.append(", ").append(context.getString(R.string.depth)); description.append(" ").append(depth); if (location != null) { // jarak gempa float distance = quake.getLocation().distanceTo(location); String distanceString = unit.formatNumber(distance, EarthquakeDTO .FRACTION_DEPTH);; description.append(", ").append(context.getString(R.string.distance)); description.append(" ").append(distanceString); // Mendapatkan alamat berdasarkan koordinat latitude dan longitude try { Geocoder geocoder = new Geocoder(context); List<Address> addresses = geocoder.getFromLocation(location.getLatitude(), location.getLongitude(), 5); if (addresses != null && addresses.size() > 0) { // Kita hanya memerlukan satu alamat String addressLine = LocationUtils.getAddressLine(addresses.get(0)); if (!addressLine.equals("")) { // Tambahkan ke description description.append(" ").append(context.getString(R.string.conj_from)); description.append(" ").append(addressLine); } } } catch (IOException e) { // Terdapat error pada geocoder, abaikan Log.e(TAG, e.getMessage(), e); } } return description.toString(); } /** * Login ke facebook * * @param activity Activity */ public void login(Activity activity) { if (facebook.isSessionValid()) { SessionEvents.onLoginSuccess(); return; } facebook.authorize(activity, FACEBOOK_PERMISSION, new DialogListener() { @Override public void onComplete(Bundle values) { SessionEvents.onLoginSuccess(); } @Override public void onFacebookError(FacebookError e) { SessionEvents.onLoginError(e.getMessage()); } @Override public void onError(DialogError e) { SessionEvents.onLoginError(e.getMessage()); } @Override public void onCancel() { SessionEvents.onLoginError("Action cancelled"); } }); } /** * Menghapus access token pada memory dan membersihkan browser cookies */ public void logout() { SessionEvents.onLogoutBegin(); AsyncFacebookRunner runner = new AsyncFacebookRunner(facebook); runner.logout(context, new BaseRequestListener() { @Override public void onComplete(String response, Object state) { // callback harus berjalan pada UI thread, tidak pada background thread handler.post(new Runnable() { @Override public void run() { SessionEvents.onLogoutFinish(); } }); } }); } /** * Mendapatkan objek facebook * @return Facebook */ public Facebook getFacebook() { return facebook; } /** * Mendapatkan apakah sesi Facebook valid atau tidak. * * @return True jika valid, false jika tidak */ public boolean isSessionValid() { return facebook.isSessionValid(); } private class SessionListener implements AuthListener, LogoutListener { @Override public void onAuthSucceed() { SessionStore.save(facebook, context); } @Override public void onAuthFail(String error) { } @Override public void onLogoutBegin() { } @Override public void onLogoutFinish() { SessionStore.clear(context); } } }