/*
* Copyright 2012 Javier Pérez Pacheco and Francisco Díaz Rodriguez
* TweetTopics 2.0
* javielinux@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.
*/
package com.javielinux.updatestatus;
import android.app.Service;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import com.android.dataframework.DataFramework;
import com.android.dataframework.Entity;
import com.facebook.android.AsyncFacebookRunner;
import com.facebook.android.AsyncFacebookRunner.RequestListener;
import com.facebook.android.Facebook;
import com.facebook.android.FacebookError;
import com.javielinux.facebook.FacebookHandler;
import com.javielinux.task.*;
import com.javielinux.task.DirectMessageAsyncTask.DirectMessageAsyncTaskResponder;
import com.javielinux.task.ImageUploadAsyncTask.ImageUploadAsyncTaskResponder;
import com.javielinux.task.ImageUploadAsyncTask.ImageUploadResult;
import com.javielinux.task.UploadStatusAsyncTask.UploadStatusAsyncTaskResponder;
import com.javielinux.task.UploadTwitlongerAsyncTask.UploadTwitlongerAsyncTaskResponder;
import com.javielinux.tweettopics2.NewStatusActivity;
import com.javielinux.tweettopics2.R;
import com.javielinux.twitter.ConnectionManager;
import com.javielinux.utils.*;
import twitter4j.Twitter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.StringTokenizer;
public class ServiceUpdateStatus extends Service implements UploadStatusAsyncTaskResponder, ImageUploadAsyncTaskResponder,
DirectMessageAsyncTaskResponder, RetweetStatusAsyncTask.RetweetStatusAsyncTaskResponder {
private ArrayList<Long> usersId;
private HashMap<Long,String> usersNetwork;
private ArrayList<String> photos;
private ArrayList<String> photosRemoved;
private Entity entityStatus = null;
private long currentIdUser = 0;
public static Twitter twitter;
private String text = "";
private String baseURLImage = "";
@Override
public IBinder onBind(Intent intent) {
return null;
}
/**
* For all versión, lower 2.0
* @param intent
* @param startId
*/
@Override
public void onStart(Intent intent, int startId) {
handleCommand(intent);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
handleCommand(intent);
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
}
public void handleCommand(Intent intent) {
usersId = new ArrayList<Long>();
usersNetwork = new HashMap<Long, String>();
photos = new ArrayList<String>();
photosRemoved = new ArrayList<String>();
try {
DataFramework.getInstance().open(this, Utils.packageName);
} catch (Exception e) {
e.printStackTrace();
}
ConnectionManager.getInstance().open(this);
Log.d(Utils.TAG, "Creando nuevo estado");
entityStatus = DataFramework.getInstance().getTopEntity("send_tweets", "is_sent = 0", "");
if (entityStatus !=null) {
ArrayList<Long> auxUsersTwitter = new ArrayList<Long>();
ArrayList<Long> auxUsersOthers = new ArrayList<Long>();
String users = entityStatus.getString("users");
for (String user : users.split(",")) {
try {
if (!user.equals("")) {
Entity e = new Entity("users", Long.parseLong(user));
if (e.getString("service").equals("") || e.getString("service").equals("twitter.com")) {
auxUsersTwitter.add(Long.parseLong(user));
} else {
auxUsersOthers.add(Long.parseLong(user));
}
}
} catch (NumberFormatException e) {
e.printStackTrace();
}
}
// ordenar poniendo los de twitter los primeros
for (long user : auxUsersTwitter) {
usersId.add(user);
usersNetwork.put(user, ConstantUtils.NETWORK_TWITTER_NAME);
}
for (long user : auxUsersOthers) {
usersId.add(user);
usersNetwork.put(user, ConstantUtils.NETWORK_FACEBOOK_NAME);
}
text = entityStatus.getString("text");
String photos = entityStatus.getString("photos");
if (!photos.equals("")) {
int type = Integer.parseInt(Utils.getPreference(this).getString("prf_service_image", "1"));
if (type==1) {
baseURLImage = NewStatusActivity.URL_BASE_YFROG;
} else if (type==2) {
baseURLImage = NewStatusActivity.URL_BASE_TWITPIC;
} else if (type==3) {
baseURLImage = NewStatusActivity.URL_BASE_LOCKERZ;
}
StringTokenizer tokens = new StringTokenizer(photos, "--");
while(tokens.hasMoreTokens()) {
String photo = tokens.nextToken();
if (!photo.equals("")) {
this.photos.add(photo);
}
}
}
// empezamos a enviar
try {
sendNotification(this.getString(R.string.update_status_uploading_msg), false);
} catch (Resources.NotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
launchTasks();
}
stopSelf();
}
@Override
public void onDestroy() {
super.onDestroy();
DataFramework.getInstance().close();
}
private void launchTasks() {
if (photos.size()>0) {
twitter = ConnectionManager.getInstance().getTwitter(usersId.get(0));
try {
sendNotification(this.getString(R.string.update_status_uploading_image), false);
} catch (Resources.NotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
uploadImage(photos.get(0));
} else {
if (usersId.size()>0) {
sendTweet(usersId.get(0));
} else {
deleteTweet();
try {
sendNotification(this.getString(R.string.update_status_correct), false);
} catch (Resources.NotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
NotificationUtils.cancelNotification(this);
Intent update = new Intent();
update.putExtra("refresh-column", TweetTopicsUtils.TWEET_TYPE_TIMELINE);
update.setAction(Intent.ACTION_VIEW);
sendOrderedBroadcast(update, null);
}
}
}
private void sendTweet(long id) {
currentIdUser = id;
if (usersNetwork.get(id).equals("facebook")) {
updateStatusFacebook();
} else {
twitter = ConnectionManager.getInstance().getTwitter(id);
if (entityStatus.getInt("type_id") == 3) { // retweet
retweetMessage();
} else {
int shortURLLength = PreferenceUtils.getShortURLLength(this);
int shortURLLengthHttps = PreferenceUtils.getShortURLLengthHttps(this);
if (Utils.getLenghtTweet(text, shortURLLength, shortURLLengthHttps)>140) {
if (entityStatus.getInt("type_id") == 1) { // normal
if (entityStatus.getInt("mode_tweetlonger") == NewStatusActivity.MODE_TL_TWITLONGER) { // twitlonger
updateTwitlonger();
} else {
updateStatus(NewStatusActivity.MODE_TL_N_TWEETS);
}
} else { // directo
directMessage(NewStatusActivity.MODE_TL_N_TWEETS);
}
} else {
if (entityStatus.getInt("type_id") == 1) { // normal
updateStatus(NewStatusActivity.MODE_TL_NONE);
} else { // directo
directMessage(NewStatusActivity.MODE_TL_NONE);
}
}
}
}
}
private void deleteCurrentId() {
usersId.remove(currentIdUser);
}
private void setErrorTweet() {
if (entityStatus.getLong("tweet_programmed_id")>0) {
Entity ent = entityStatus.getEntity("tweet_programmed_id");
ent.setValue("is_sent", 2);
ent.save();
}
entityStatus.setValue("is_sent", 1);
entityStatus.save();
}
private void deleteTweet() {
if (entityStatus.getLong("tweet_programmed_id")>0) {
Entity ent = entityStatus.getEntity("tweet_programmed_id");
ent.setValue("is_sent", 1);
ent.save();
}
if (entityStatus.getLong("tweet_draft_id")>0) {
Entity ent = entityStatus.getEntity("tweet_draft_id");
ent.delete();
}
for (String photo : photosRemoved) {
File f = new File(Utils.appUploadImageDirectory+photo);
if (f.exists()) f.delete();
}
try {
// try {
// DataFramework.getInstance().open(this, Utils.packageName);
// } catch (Exception e) {
// e.printStackTrace();
// }
entityStatus.delete();
// DataFramework.getInstance().close();
} catch (IllegalStateException e) {
} catch (Exception e) {}
}
/*
*
* Update status Facebook
*
*/
public void updateStatusFacebook() {
FacebookHandler fbh = new FacebookHandler(null);
Facebook facebook = fbh.loadUser(currentIdUser);
if (facebook!=null) {
Bundle params = new Bundle();
params.putString("message", text);
String stream = "me/feed";
if (photosRemoved.size()>0) {
stream = "me/photos";
byte[] data = null;
Bitmap bi = BitmapFactory.decodeFile(Utils.appUploadImageDirectory+ photosRemoved.get(0));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bi.compress(Bitmap.CompressFormat.JPEG, 100, baos);
data = baos.toByteArray();
params.putByteArray("picture", data);
}
AsyncFacebookRunner mAsyncRunner = new AsyncFacebookRunner(facebook);
mAsyncRunner.request(stream, params, "POST", new RequestListener() {
@Override
public void onMalformedURLException(MalformedURLException e, Object state) {
}
@Override
public void onIOException(IOException e, Object state) {
}
@Override
public void onFileNotFoundException(FileNotFoundException e, Object state) {
}
@Override
public void onFacebookError(FacebookError e, Object state) {
}
@Override
public void onComplete(String response, Object state) {
deleteCurrentId();
launchTasks();
/*ServiceUpdateStatus.this.runOnUiThread(new Runnable() {
public void run() {
Utils.showMessage(ServiceUpdateStatus.this, "Mensaje publicado");
}
});*/
}
}, "foo");
}
}
/*
*
* Update status
*
*/
public void updateStatus(int modeTL) {
new UploadStatusAsyncTask(this, this, twitter, modeTL).execute(text, entityStatus.getString("reply_tweet_id"), entityStatus.getString("use_geo"));
}
@Override
public void uploadStatusCancelled() {
}
@Override
public void uploadStatusLoaded(boolean error) {
if (error) {
setErrorTweet();
try {
sendNotification(this.getString(R.string.update_status_error_msg), true);
} catch (Resources.NotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
this.stopSelf();
} else {
deleteCurrentId();
launchTasks();
}
}
@Override
public void uploadStatusLoading() {
}
/*
*
* Update Twitlonger
*
*/
public void updateTwitlonger() {
new UploadTwitlongerAsyncTask(this, new UploadTwitlongerAsyncTaskResponder() {
@Override
public void uploadTwitlongerLoading() {
}
@Override
public void uploadTwitlongerCancelled() {
}
@Override
public void uploadTwitlongerLoaded(boolean error) {
if (error) {
setErrorTweet();
try {
sendNotification(ServiceUpdateStatus.this.getString(R.string.update_status_error_msg), true);
} catch (Resources.NotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
ServiceUpdateStatus.this.stopSelf();
} else {
deleteCurrentId();
launchTasks();
}
}
}, twitter).execute(text, entityStatus.getString("reply_tweet_id"), entityStatus.getString("use_geo"));
}
/*
*
* retweet
*
*/
public void retweetMessage() {
new RetweetStatusAsyncTask(this, twitter).execute(entityStatus.getLong("reply_tweet_id"));
}
@Override
public void retweetStatusLoading() {
}
@Override
public void retweetStatusCancelled() {
}
@Override
public void retweetStatusLoaded(boolean error) {
if (error) {
setErrorTweet();
try {
sendNotification(this.getString(R.string.update_status_error_msg), true);
} catch (Resources.NotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
this.stopSelf();
} else {
deleteCurrentId();
launchTasks();
}
}
/*
*
* Direct message
*
*/
public void directMessage(int modeTL) {
new DirectMessageAsyncTask(this, twitter, modeTL).execute(text, entityStatus.getString("username_direct"));
}
@Override
public void directMessageStatusCancelled() {
}
@Override
public void directMessageStatusLoaded(boolean error) {
if (error) {
setErrorTweet();
try {
sendNotification(this.getString(R.string.update_status_error_msg), true);
} catch (Resources.NotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
this.stopSelf();
} else {
deleteCurrentId();
launchTasks();
}
}
@Override
public void directMessageStatusLoading() {
}
/*
*
* Upload image
*
*/
public void uploadImage(String file) {
new ImageUploadAsyncTask(this, twitter).execute(file);
}
@Override
public void imageUploadCancelled() {
}
@Override
public void imageUploadLoaded(ImageUploadResult imageUploadResult) {
boolean error = false;
if (imageUploadResult.error) {
error = true;
} else {
if ( (imageUploadResult.url!=null) && !imageUploadResult.url.equals("") ) {
String name = "";
StringTokenizer tokens = new StringTokenizer(imageUploadResult.file, ".");
if (tokens.hasMoreTokens()) {
name = tokens.nextToken();
}
String base = baseURLImage + name;
//Log.d(Utils.TAG, "Reemplazando " + base + " por " + imageUploadResult.url);
text = text.replace(base, imageUploadResult.url);
photos.remove(imageUploadResult.file);
photosRemoved.add(imageUploadResult.file);
} else {
error = true;
}
}
if (error) {
setErrorTweet();
try {
sendNotification(this.getString(R.string.update_status_error_image), true);
} catch (Resources.NotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
this.stopSelf();
} else {
launchTasks();
}
}
@Override
public void imageUploadLoading() {
}
/*
*
* Notificaciones
*
*/
private void sendNotification(String text, boolean tryAgain) {
if (entityStatus.getLong("tweet_programmed_id")<=0) { // enviar sólo si no es un tweet programado
NotificationUtils.sendNotification(this, getString(R.string.app_name), text, "", true, false);
}
}
}