/**
* Copyright 2013 Abewy. All rights reserved
*
* @date 2 avr. 2013
* @author Jonathan
*/
package com.abewy.android.apps.klyph.service;
import java.io.File;
import java.io.FileNotFoundException;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import com.abewy.android.apps.klyph.KlyphBundleExtras;
import com.abewy.android.apps.klyph.core.util.AttrUtil;
import com.abewy.android.apps.klyph.core.util.NotificationUtil;
import com.abewy.android.apps.klyph.R;
import com.facebook.HttpMethod;
import com.facebook.Request;
import com.facebook.Session;
public class UploadPhotoService extends Service
{
private static final String MY_PHOTOS = "me/photos";
private static final String MY_VIDEOS = "me/videos";
private static final String PICTURE_PARAM = "picture";
private Looper mServiceLooper;
private ServiceHandler mServiceHandler;
public UploadPhotoService()
{
super();
}
@Override
public void onCreate()
{
HandlerThread thread = new HandlerThread("ServiceStartArguments", android.os.Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper, new WeakReference<Service>(this));
}
@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
if (intent != null)
{
Message msg = mServiceHandler.obtainMessage();
Bundle bundle = new Bundle();
bundle.putStringArrayList(KlyphBundleExtras.UPLOAD_PHOTO_URIS,
intent.getStringArrayListExtra(KlyphBundleExtras.UPLOAD_PHOTO_URIS));
bundle.putString(KlyphBundleExtras.UPLOAD_PHOTO_CAPTION,
intent.getStringExtra(KlyphBundleExtras.UPLOAD_PHOTO_CAPTION));
bundle.putString(KlyphBundleExtras.UPLOAD_PHOTO_PLACE,
intent.getStringExtra(KlyphBundleExtras.UPLOAD_PHOTO_PLACE));
bundle.putString(KlyphBundleExtras.UPLOAD_PHOTO_PRIVACY,
intent.getStringExtra(KlyphBundleExtras.UPLOAD_PHOTO_PRIVACY));
bundle.putString(KlyphBundleExtras.UPLOAD_PHOTO_ALBUM,
intent.getStringExtra(KlyphBundleExtras.UPLOAD_PHOTO_ALBUM));
bundle.putStringArrayList(KlyphBundleExtras.UPLOAD_PHOTO_TAGS,
intent.getStringArrayListExtra(KlyphBundleExtras.UPLOAD_PHOTO_TAGS));
msg.setData(bundle);
mServiceHandler.sendMessage(msg);
}
// If we get killed, after returning from here, restart
return START_STICKY;
}
@Override
public IBinder onBind(Intent intent)
{
return null;
}
static class Image
{
private String uri;
private String album;
private String caption;
private String place;
private String privacy;
private List<String> tags;
public Image(String uri, String album, String caption, String place, String privacy, List<String> tags)
{
this.uri = uri;
this.album = album;
this.caption = caption;
this.place = place;
this.privacy = privacy;
this.tags = tags;
}
public String getUri()
{
return uri;
}
public String getAlbum()
{
return album;
}
public String getCaption()
{
return caption;
}
public String getPlace()
{
return place;
}
public String getPrivacy()
{
return privacy;
}
public List<String> getTags()
{
return tags;
}
}
// Handler that receives messages from the thread
private static final class ServiceHandler extends Handler
{
private final WeakReference<Service> service;
private List<Image> images;
private int total = 0;
private int errors = 0;
private boolean isLoading = false;
private final int notificationId;
private final NotificationCompat.Builder builder;
public ServiceHandler(Looper looper, WeakReference<Service> service)
{
super(looper);
this.service = service;
images = new ArrayList<UploadPhotoService.Image>();
notificationId = (int) System.currentTimeMillis();
builder = new NotificationCompat.Builder(service.get()).setSmallIcon(R.drawable.ic_notification)
.setContentTitle(service.get().getString(R.string.uploading_images))
.setTicker(service.get().getString(R.string.uploading_images)).setAutoCancel(true)
.setOnlyAlertOnce(false);
NotificationUtil.setDummyIntent(service.get(), builder);
}
@Override
public void handleMessage(Message msg)
{
Bundle bundle = msg.getData();
List<String> path = bundle.getStringArrayList(KlyphBundleExtras.UPLOAD_PHOTO_URIS);
String caption = bundle.getString(KlyphBundleExtras.UPLOAD_PHOTO_CAPTION);
String place = bundle.getString(KlyphBundleExtras.UPLOAD_PHOTO_PLACE);
String privacy = bundle.getString(KlyphBundleExtras.UPLOAD_PHOTO_PRIVACY);
String album = bundle.getString(KlyphBundleExtras.UPLOAD_PHOTO_ALBUM);
List<String> tags = bundle.getStringArrayList(KlyphBundleExtras.UPLOAD_PHOTO_TAGS);
if (album == null)
{
album = "me";
}
if (path != null && path.size() > 0)
{
for (String uri : path)
{
Image image = new Image(uri, album, caption, place, privacy, tags);
images.add(image);
total++;
}
if (isLoading == false)
{
uploadNext();
}
}
}
private void uploadNext()
{
isLoading = true;
final Image image = images.get(0);
images.remove(0);
Bundle parameters = new Bundle();
if (image.getCaption() != null && image.getCaption().length() > 0)
{
parameters.putString("caption", image.getCaption());
}
if (image.getPlace() != null && image.getPlace().length() > 0)
{
parameters.putString("place", image.getPlace());
}
if (image.getPrivacy() != null && image.getPrivacy().length() > 0)
{
parameters.putString("privacy", image.getPrivacy());
}
if (image.getTags() != null && image.getTags().size() > 0)
{
JSONArray array = new JSONArray();
for (String id : image.getTags())
{
Log.d("UpldoadService", "tag id " + id);
JSONObject object = new JSONObject();
try
{
object.putOpt("tag_uid", id);
}
catch (JSONException e)
{
continue;
}
array.put(object);
}
parameters.putString("tags", array.toString());
}
File file = new File(image.getUri());
ParcelFileDescriptor descriptor;
try
{
descriptor = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
}
catch (FileNotFoundException e)
{
e.printStackTrace();
showFileNotFoundNotification(image.getUri());
return;
}
parameters.putParcelable(PICTURE_PARAM, descriptor);
Request request = new Request(Session.getActiveSession(), image.getAlbum() + "/photos", parameters, HttpMethod.POST,
new Request.Callback() {
@Override
public void onCompleted(com.facebook.Response response)
{
if (response.getError() != null)
{
errors++;
Log.d("UploadService", response.getError().toString());
showErrorNotification(response.getError().getErrorMessage());
}
if (images.size() > 0)
{
uploadNext();
}
else
{
showEndNotification();
service.get().stopSelf();
}
}
});
showNotification();
Request.executeBatchAsync(request);
}
private void showFileNotFoundNotification(String uri)
{
if (service.get() == null)
return;
Service s = service.get();
final int notificationId = (int) System.currentTimeMillis();
NotificationCompat.Builder builder = new NotificationCompat.Builder(service.get()).setSmallIcon(R.drawable.ic_notification)
.setTicker(service.get().getString(R.string.upload_error)).setAutoCancel(true)
.setOnlyAlertOnce(true);
NotificationUtil.setDummyIntent(service.get(), builder);
builder.setContentTitle(service.get().getString(R.string.upload_error));
builder.setContentText(service.get().getString(R.string.file_not_found, uri));
final NotificationManager mNotificationManager = (NotificationManager) s
.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(AttrUtil.getString(s, R.string.app_name), notificationId, builder.build());
}
private void showNotification()
{
if (service.get() == null)
return;
Service s = service.get();
builder.setTicker(s.getString(R.string.uploading_image_of, total - images.size(), total));
builder.setContentText(s.getString(R.string.uploading_image_of, total - images.size(), total));
builder.setProgress(100, 0, true);
final NotificationManager mNotificationManager = (NotificationManager) s
.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(AttrUtil.getString(s, R.string.app_name), notificationId, builder.build());
}
private void showEndNotification()
{
if (service.get() == null)
return;
Service s = service.get();
builder.setTicker(service.get().getString(R.string.upload_complete));
builder.setContentTitle(service.get().getString(R.string.upload_complete));
builder.setContentText(s.getString(R.string.n_uploaded_images, total - errors));
builder.setProgress(0, 0, false);
final NotificationManager mNotificationManager = (NotificationManager) s
.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(AttrUtil.getString(s, R.string.app_name), notificationId, builder.build());
}
private void showErrorNotification(String fbError)
{
if (service.get() == null || fbError == null)
return;
Service s = service.get();
final int notificationId = (int) System.currentTimeMillis();
NotificationCompat.Builder builder = new NotificationCompat.Builder(service.get()).setSmallIcon(R.drawable.ic_notification)
.setTicker(service.get().getString(R.string.upload_error)).setAutoCancel(true)
.setOnlyAlertOnce(true);
NotificationUtil.setDummyIntent(service.get(), builder);
builder.setContentTitle(service.get().getString(R.string.upload_error));
builder.setContentText(fbError);
final NotificationManager mNotificationManager = (NotificationManager) s
.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(AttrUtil.getString(s, R.string.app_name), notificationId, builder.build());
}
}
}