au.com.infiniterecursion.vidiom.utils.PublishingUtils.java Source code

Java tutorial

Introduction

Here is the source code for au.com.infiniterecursion.vidiom.utils.PublishingUtils.java

Source

package au.com.infiniterecursion.vidiom.utils;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.SocketException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.UnknownHostException;
import java.nio.charset.Charset;
import java.nio.charset.IllegalCharsetNameException;
import java.nio.charset.UnsupportedCharsetException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.http.HttpVersion;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.util.EntityUtils;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.preference.PreferenceManager;
import android.util.Log;
import au.com.infiniterecursion.vidiom.VidiomApp;
import au.com.infiniterecursion.vidiom.activity.VidiomActivity;
import au.com.infiniterecursion.vidiom.sslemail.SSLEmailSender;
import au.com.infiniterecursion.vidiom.utils.GoogleAuthoriser.AuthorizationListener;
import au.com.infiniterecursion.vidiompro.R;

import com.facebook.android.Facebook;
import com.facebook.android.Util;

/*
 * Vidiom Library Activity 
 * 
 * AUTHORS:
 * 
 * Andy Nicholson
 * 
 * 2010
 * Copyright Infinite Recursion Pty Ltd.
 * http://www.infiniterecursion.com.au
 */

public class PublishingUtils {

    private static final String TAG = "VidiomTag-PublishingUtils";

    private Resources res;
    private DBUtils dbutils;

    // Video hosting services , internal classification - for tracking uploads
    // in progress.
    public static final int TYPE_FB = 0;
    public static final int TYPE_YT = 1;
    public static final int TYPE_FTP = 2;
    public static final int TYPE_VB = 3;

    private static final String INITIAL_UPLOAD_URL = "http://uploads.gdata.youtube.com/resumable/feeds/api/users/default/uploads";
    private static final String DEFAULT_VIDEO_CATEGORY = "News";
    private static final String DEFAULT_VIDEO_TAGS = "mobile";
    private static final String YOUTUBE_PLAYER_URL = "http://www.youtube.com/watch?feature=player_profilepage&v=";

    private static final int MAX_RETRIES = 5;
    private static final int BACKOFF = 4; // base of exponential backoff

    private String clientLoginToken = null;
    private String youTubeName = null;

    private double currentFileSize = 0;
    private double totalBytesUploaded = 0;
    private int numberOfRetries = 0;
    private String tags = null;
    private GoogleAuthoriser authorizer;

    private VidiomApp mainapp;

    public PublishingUtils(Resources res, VidiomApp app) {

        this.res = res;
        this.dbutils = app.getDBUtils();
        this.mainapp = app;
    }

    public static String showDate(long timemillis) {

        if (timemillis <= 0)
            return "N/A";

        Calendar cal;
        SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss");
        cal = Calendar.getInstance();
        cal.setTimeInMillis(timemillis);
        return sdf.format(cal.getTime());

    }

    public static String getVideoServiceStringFromServiceCode(Context c, int service_code) {
        String service = "";
        switch (service_code) {
        case PublishingUtils.TYPE_YT:
            service = c.getString(R.string.youtube);
            break;
        case PublishingUtils.TYPE_VB:
            service = c.getString(R.string.videobin);
            break;
        case PublishingUtils.TYPE_FB:
            service = c.getString(R.string.facebook);
            break;
        case PublishingUtils.TYPE_FTP:
            service = c.getString(R.string.ftp_server);
            break;
        }
        return service;
    }

    /*
     * 
     * Methods for publishing the video
     */

    // videoUploadToFacebook modified from
    // http://code.google.com/p/stickman-android/source/browse/trunk/src/org/hackday/stickman/upload/FacebookHelper.java?spec=svn31&r=31
    // http://www.apache.org/licenses/LICENSE-2.0
    //
    // Changed by Andy Nicholson
    //
    // Facebook uploading
    //
    public Thread videoUploadToFacebook(final Activity activity, final Handler handler, final Facebook mFacebook,
            final String path, final String title, final String description, final String emailAddress,
            final long sdrecord_id) {

        // Make the progress bar view visible.
        ((VidiomActivity) activity).startedUploading(PublishingUtils.TYPE_FB);
        final Resources res = activity.getResources();

        Thread t = new Thread(new Runnable() {
            public void run() {
                // Do background task.
                // Track errors
                boolean failed = false;

                Log.i(TAG, "Upload starting");
                // Initialising REST API video.upload parameters
                Bundle params = new Bundle();

                params.putString("method", "facebook.video.upload");
                params.putString("format", "json");
                params.putString("title", title);
                params.putString("description", description);
                params.putString("call_id", String.valueOf(System.currentTimeMillis()));
                params.putString("v", "1.0");
                params.putString("oauth_token", mFacebook.getAccessToken());

                // Reading input file
                try {
                    File videoFile = new File(path);
                    byte[] data = null;
                    try {

                        // XXX
                        // SPLIT THIS INTO 5K chunks!!
                        // XXX

                        data = new byte[(int) videoFile.length()];
                    } catch (OutOfMemoryError e) {
                        failed = true;
                    }
                    if (data != null) {
                        InputStream is = new FileInputStream(videoFile);
                        is.read(data);
                        params.putByteArray(videoFile.getName(), data);
                    }
                } catch (Exception ex) {
                    Log.e(TAG, "Cannot read video file :", ex);
                }

                // Sending POST request to Facebook
                String response = null;
                String url = "https://api-video.facebook.com/restserver.php";

                try {
                    if (!failed) {
                        response = Util.openUrl(url, "POST", params);
                    }
                    // SessionEvents.onUploadComplete(response);
                } catch (FileNotFoundException e) {
                    // SessionEvents.onFileNotFoundException(e);
                    failed = true;
                    e.printStackTrace();
                } catch (MalformedURLException e) {
                    // SessionEvents.onMalformedURLException(e);
                    failed = true;
                    e.printStackTrace();
                } catch (IOException e) {
                    // SessionEvents.onIOException(e);
                    failed = true;
                    e.printStackTrace();
                } catch (OutOfMemoryError e) {
                    failed = true;
                    e.printStackTrace();
                }

                if (failed) {
                    // Use the handler to execute a Runnable on the
                    // main thread in order to have access to the
                    // UI elements.

                    mainapp.removeSDFileRecordIDfromUploadingTrack(sdrecord_id, TYPE_FB);

                    handler.postDelayed(new Runnable() {
                        public void run() {
                            // Update UI

                            // Indicate back to calling activity the result!
                            // update uploadInProgress state also.

                            ((VidiomActivity) activity).finishedUploading(false);
                            ((VidiomActivity) activity)
                                    .createNotification(res.getString(R.string.upload_to_facebook_failed_));
                        }
                    }, 0);

                    return;
                }

                Log.i(TAG, "Uploading to facebook complete. Response is " + response);

                // response is JSON
                JSONObject fb_response = null;
                // decode, and grab URL
                try {
                    fb_response = (JSONObject) new JSONTokener(response).nextValue();
                } catch (JSONException e) {
                    //
                    e.printStackTrace();
                    fb_response = null;
                }
                String hosted_url = "facebook.com";

                if (fb_response != null) {

                    try {
                        hosted_url = fb_response.getString("link");
                        Log.i(TAG, "Facebook hosted url is : " + hosted_url);
                    } catch (JSONException e) {
                        //
                        e.printStackTrace();
                        hosted_url = null;
                    }

                    if (hosted_url != null) {
                        // Log record of this URL in POSTs table
                        dbutils.creatHostDetailRecordwithNewVideoUploaded(sdrecord_id, url, hosted_url, "");

                        mainapp.removeSDFileRecordIDfromUploadingTrack(sdrecord_id, TYPE_FB);

                        // Use the handler to execute a Runnable on the
                        // main thread in order to have access to the
                        // UI elements.
                        handler.postDelayed(new Runnable() {

                            public void run() {
                                // Update UI

                                // Indicate back to calling activity the result!
                                // update uploadInProgress state also.

                                ((VidiomActivity) activity).finishedUploading(true);
                                ((VidiomActivity) activity)
                                        .createNotification(res.getString(R.string.upload_to_facebook_succeeded_));

                            }
                        }, 0);
                    }

                } else {

                    // an error -- fb_response is NULL.
                    mainapp.removeSDFileRecordIDfromUploadingTrack(sdrecord_id, TYPE_FB);

                    handler.postDelayed(new Runnable() {
                        public void run() {
                            // Update UI

                            // Indicate back to calling activity the result!
                            // update uploadInProgress state also.

                            ((VidiomActivity) activity).finishedUploading(false);
                            ((VidiomActivity) activity)
                                    .createNotification(res.getString(R.string.upload_to_facebook_failed_));
                        }
                    }, 0);

                }

                if (emailAddress != null && fb_response != null && hosted_url != null) {

                    // EmailSender through IR controlled gmail system.
                    SSLEmailSender sender = new SSLEmailSender(
                            activity.getString(R.string.automatic_email_username),
                            activity.getString(R.string.automatic_email_password)); // consider
                    // this
                    // public
                    // knowledge.
                    try {
                        sender.sendMail(activity.getString(R.string.vidiom_automatic_email), // subject.getText().toString(),
                                activity.getString(R.string.url_of_hosted_video_is_) + " " + hosted_url, // body.getText().toString(),
                                activity.getString(R.string.automatic_email_from), // from.getText().toString(),
                                emailAddress // to.getText().toString()
                        );
                    } catch (Exception e) {
                        Log.e(TAG, e.getMessage(), e);
                    }
                }

            }
        });

        t.start();

        return t;

    }

    public Thread videoUploadToVideoBin(final Activity activity, final Handler handler,
            final String video_absolutepath, final String title, final String description,
            final String emailAddress, final long sdrecord_id) {

        Log.d(TAG, "doPOSTtoVideoBin starting");

        // Make the progress bar view visible.
        ((VidiomActivity) activity).startedUploading(PublishingUtils.TYPE_VB);
        final Resources res = activity.getResources();

        Thread t = new Thread(new Runnable() {
            public void run() {
                // Do background task.

                boolean failed = false;

                HttpClient client = new DefaultHttpClient();
                client.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);

                URI url = null;
                try {
                    url = new URI(res.getString(R.string.http_videobin_org_add));
                } catch (URISyntaxException e) {
                    // Ours is a fixed URL, so not likely to get here.
                    mainapp.removeSDFileRecordIDfromUploadingTrack(sdrecord_id, TYPE_VB);

                    e.printStackTrace();
                    return;

                }
                HttpPost post = new HttpPost(url);
                MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);

                File file = new File(video_absolutepath);
                entity.addPart(res.getString(R.string.video_bin_API_videofile), new FileBody(file));

                try {
                    entity.addPart(res.getString(R.string.video_bin_API_api),
                            new StringBody("1", "text/plain", Charset.forName("UTF-8")));

                    // title
                    entity.addPart(res.getString(R.string.video_bin_API_title),
                            new StringBody(title, "text/plain", Charset.forName("UTF-8")));

                    // description
                    entity.addPart(res.getString(R.string.video_bin_API_description),
                            new StringBody(description, "text/plain", Charset.forName("UTF-8")));

                } catch (IllegalCharsetNameException e) {
                    // error
                    e.printStackTrace();
                    failed = true;

                } catch (UnsupportedCharsetException e) {
                    // error
                    e.printStackTrace();
                    return;
                } catch (UnsupportedEncodingException e) {
                    // error
                    e.printStackTrace();
                    failed = true;
                }

                post.setEntity(entity);

                // Here we go!
                String response = null;
                try {
                    response = EntityUtils.toString(client.execute(post).getEntity(), "UTF-8");
                } catch (ParseException e) {
                    // error
                    e.printStackTrace();
                    failed = true;
                } catch (ClientProtocolException e) {
                    // error
                    e.printStackTrace();
                    failed = true;
                } catch (IOException e) {
                    // error
                    e.printStackTrace();
                    failed = true;
                }

                client.getConnectionManager().shutdown();

                // CHECK RESPONSE FOR SUCCESS!!
                if (!failed && response != null
                        && response.matches(res.getString(R.string.video_bin_API_good_re))) {
                    // We got back HTTP response with valid URL
                    Log.d(TAG, " video bin got back URL " + response);

                } else {
                    Log.d(TAG, " video bin got eror back:\n" + response);
                    failed = true;
                }

                if (failed) {
                    // Use the handler to execute a Runnable on the
                    // main thread in order to have access to the
                    // UI elements.
                    mainapp.removeSDFileRecordIDfromUploadingTrack(sdrecord_id, TYPE_VB);

                    handler.postDelayed(new Runnable() {
                        public void run() {
                            // Update UI

                            // Indicate back to calling activity the result!
                            // update uploadInProgress state also.

                            ((VidiomActivity) activity).finishedUploading(false);

                            ((VidiomActivity) activity)
                                    .createNotification(res.getString(R.string.upload_to_videobin_org_failed_));
                        }
                    }, 0);

                    return;
                }

                // XXX Convert to preference for auto-email on videobin post
                // XXX ADD EMAIL NOTIF to all other upload methods
                // stuck on YES here, if email is defined.

                if (emailAddress != null && response != null) {

                    // EmailSender through IR controlled gmail system.
                    SSLEmailSender sender = new SSLEmailSender(
                            activity.getString(R.string.automatic_email_username),
                            activity.getString(R.string.automatic_email_password)); // consider
                    // this
                    // public
                    // knowledge.
                    try {
                        sender.sendMail(activity.getString(R.string.vidiom_automatic_email), // subject.getText().toString(),
                                activity.getString(R.string.url_of_hosted_video_is_) + " " + response, // body.getText().toString(),
                                activity.getString(R.string.automatic_email_from), // from.getText().toString(),
                                emailAddress // to.getText().toString()
                        );
                    } catch (Exception e) {
                        Log.e(TAG, e.getMessage(), e);
                    }
                }

                // Log record of this URL in POSTs table
                dbutils.creatHostDetailRecordwithNewVideoUploaded(sdrecord_id,
                        res.getString(R.string.http_videobin_org_add), response, "");

                mainapp.removeSDFileRecordIDfromUploadingTrack(sdrecord_id, TYPE_VB);

                // Use the handler to execute a Runnable on the
                // main thread in order to have access to the
                // UI elements.
                handler.postDelayed(new Runnable() {
                    public void run() {
                        // Update UI

                        // Indicate back to calling activity the result!
                        // update uploadInProgress state also.

                        ((VidiomActivity) activity).finishedUploading(true);
                        ((VidiomActivity) activity)
                                .createNotification(res.getString(R.string.upload_to_videobin_org_succeeded_));

                    }
                }, 0);
            }
        });

        t.start();

        return t;

    }

    public Thread videoUploadToFTPserver(final Activity activity, final Handler handler,
            final String latestVideoFile_filename, final String latestVideoFile_absolutepath,
            final String emailAddress, final long sdrecord_id) {

        Log.d(TAG, "doVideoFTP starting");

        // Make the progress bar view visible.
        ((VidiomActivity) activity).startedUploading(PublishingUtils.TYPE_FTP);

        final Resources res = activity.getResources();

        Thread t = new Thread(new Runnable() {
            public void run() {
                // Do background task.
                // FTP; connect preferences here!
                //
                SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity.getBaseContext());
                String ftpHostName = prefs.getString("defaultFTPhostPreference", null);
                String ftpUsername = prefs.getString("defaultFTPusernamePreference", null);
                String ftpPassword = prefs.getString("defaultFTPpasswordPreference", null);

                // use name of local file.
                String ftpRemoteFtpFilename = latestVideoFile_filename;

                // FTP
                FTPClient ftpClient = new FTPClient();
                InetAddress uploadhost = null;
                try {

                    uploadhost = InetAddress.getByName(ftpHostName);
                } catch (UnknownHostException e1) {
                    // If DNS resolution fails then abort immediately - show
                    // dialog to
                    // inform user first.
                    e1.printStackTrace();
                    Log.e(TAG, " got exception resolving " + ftpHostName + " - video uploading failed.");
                    uploadhost = null;
                }

                if (uploadhost == null) {

                    // Use the handler to execute a Runnable on the
                    // main thread in order to have access to the
                    // UI elements.
                    mainapp.removeSDFileRecordIDfromUploadingTrack(sdrecord_id, TYPE_FTP);

                    handler.postDelayed(new Runnable() {
                        public void run() {
                            // Update UI

                            // Hide the progress bar
                            ((VidiomActivity) activity).finishedUploading(false);
                            ((VidiomActivity) activity)
                                    .createNotification(res.getString(R.string.upload_to_ftp_host_failed_));

                            new AlertDialog.Builder(activity).setMessage(R.string.cant_find_upload_host)
                                    .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
                                        public void onClick(DialogInterface dialog, int whichButton) {

                                        }
                                    }).show();

                        }
                    }, 0);

                    return;
                }

                boolean connected = false;

                try {
                    ftpClient.connect(uploadhost);
                    connected = true;

                } catch (SocketException e) {
                    e.printStackTrace();
                    connected = false;

                } catch (UnknownHostException e) {
                    //
                    e.printStackTrace();
                    connected = false;
                } catch (IOException e) {
                    //
                    e.printStackTrace();
                    connected = false;
                }

                if (!connected) {

                    // Use the handler to execute a Runnable on the
                    // main thread in order to have access to the
                    // UI elements.
                    mainapp.removeSDFileRecordIDfromUploadingTrack(sdrecord_id, TYPE_FTP);

                    handler.postDelayed(new Runnable() {
                        public void run() {
                            // Update UI

                            // Hide the progress bar
                            ((VidiomActivity) activity).finishedUploading(false);
                            ((VidiomActivity) activity)
                                    .createNotification(res.getString(R.string.upload_to_ftp_host_failed_));

                            new AlertDialog.Builder(activity).setMessage(R.string.cant_login_upload_host)
                                    .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
                                        public void onClick(DialogInterface dialog, int whichButton) {

                                        }
                                    }).show();

                        }
                    }, 0);

                    return;
                }

                boolean reply = false;
                try {

                    reply = ftpClient.login(ftpUsername, ftpPassword);
                } catch (IOException e) {
                    //
                    e.printStackTrace();
                    Log.e(TAG, " got exception on ftp.login - video uploading failed.");
                }

                // check the reply code here
                // If we cant login, abort after showing user a dialog.
                if (!reply) {
                    try {
                        ftpClient.disconnect();
                    } catch (IOException e) {
                        //
                        e.printStackTrace();
                    }

                    // Use the handler to execute a Runnable on the
                    // main thread in order to have access to the
                    // UI elements.

                    mainapp.removeSDFileRecordIDfromUploadingTrack(sdrecord_id, TYPE_FTP);

                    handler.postDelayed(new Runnable() {
                        public void run() {
                            // Update UI

                            // Hide the progress bar
                            ((VidiomActivity) activity).finishedUploading(false);
                            ((VidiomActivity) activity)
                                    .createNotification(res.getString(R.string.upload_to_ftp_host_failed_));

                            new AlertDialog.Builder(activity).setMessage(R.string.cant_login_upload_host)
                                    .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
                                        public void onClick(DialogInterface dialog, int whichButton) {

                                        }
                                    }).show();
                        }
                    }, 0);

                    return;
                }

                // Set File type to binary
                try {
                    ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
                } catch (IOException e) {
                    //
                    e.printStackTrace();
                    // keep going?!
                }

                // BEYOND HERE DONT USE DIALOGS!

                // Construct the input stream to send to Ftp server, from the
                // local
                // video file on the sd card
                BufferedInputStream buffIn = null;
                File file = new File(latestVideoFile_absolutepath);

                try {
                    buffIn = new BufferedInputStream(new FileInputStream(file));
                } catch (FileNotFoundException e) {
                    //
                    e.printStackTrace();
                    Log.e(TAG, " got exception on local video file - video uploading failed.");

                    // Use the handler to execute a Runnable on the
                    // main thread in order to have access to the
                    // UI elements.
                    mainapp.removeSDFileRecordIDfromUploadingTrack(sdrecord_id, TYPE_FTP);

                    handler.postDelayed(new Runnable() {
                        public void run() {
                            // Update UI

                            // Hide the progress bar
                            ((VidiomActivity) activity).finishedUploading(false);
                            ((VidiomActivity) activity)
                                    .createNotification(res.getString(R.string.upload_to_ftp_host_failed_));

                        }
                    }, 0);

                    // This is a bad error, lets abort.
                    // user dialog ?! shouldnt happen, but still...
                    return;
                }

                ftpClient.enterLocalPassiveMode();

                try {
                    // UPLOAD THE LOCAL VIDEO FILE.
                    ftpClient.storeFile(ftpRemoteFtpFilename, buffIn);
                } catch (IOException e) {
                    //
                    e.printStackTrace();
                    Log.e(TAG, " got exception on storeFile - video uploading failed.");

                    // This is a bad error, lets abort.
                    // user dialog ?! shouldnt happen, but still...
                    // Use the handler to execute a Runnable on the
                    // main thread in order to have access to the
                    // UI elements.
                    mainapp.removeSDFileRecordIDfromUploadingTrack(sdrecord_id, TYPE_FTP);

                    handler.postDelayed(new Runnable() {
                        public void run() {
                            // Update UI

                            // Hide the progress bar
                            ((VidiomActivity) activity).finishedUploading(false);
                            ((VidiomActivity) activity)
                                    .createNotification(res.getString(R.string.upload_to_ftp_host_failed_));

                        }
                    }, 0);
                    return;
                }
                try {
                    buffIn.close();
                } catch (IOException e) {
                    //
                    e.printStackTrace();
                    Log.e(TAG, " got exception on buff.close - video uploading failed.");

                    // Use the handler to execute a Runnable on the
                    // main thread in order to have access to the
                    // UI elements.
                    mainapp.removeSDFileRecordIDfromUploadingTrack(sdrecord_id, TYPE_FTP);

                    handler.postDelayed(new Runnable() {
                        public void run() {
                            // Update UI

                            // Hide the progress bar
                            ((VidiomActivity) activity).finishedUploading(false);
                            ((VidiomActivity) activity)
                                    .createNotification(res.getString(R.string.upload_to_ftp_host_failed_));

                        }
                    }, 0);
                    return;
                }
                try {
                    ftpClient.logout();
                } catch (IOException e) {
                    //
                    e.printStackTrace();
                    Log.e(TAG, " got exception on ftp logout - video uploading failed.");

                    // Use the handler to execute a Runnable on the
                    // main thread in order to have access to the
                    // UI elements.
                    mainapp.removeSDFileRecordIDfromUploadingTrack(sdrecord_id, TYPE_FTP);

                    handler.postDelayed(new Runnable() {
                        public void run() {
                            // Update UI

                            // Hide the progress bar
                            ((VidiomActivity) activity).finishedUploading(false);
                            ((VidiomActivity) activity)
                                    .createNotification(res.getString(R.string.upload_to_ftp_host_failed_));

                        }
                    }, 0);
                    return;
                }
                try {
                    ftpClient.disconnect();
                } catch (IOException e) {
                    //
                    e.printStackTrace();
                    Log.e(TAG, " got exception on ftp disconnect - video uploading failed.");

                    // Use the handler to execute a Runnable on the
                    // main thread in order to have access to the
                    // UI elements.

                    mainapp.removeSDFileRecordIDfromUploadingTrack(sdrecord_id, TYPE_FTP);

                    handler.postDelayed(new Runnable() {
                        public void run() {
                            // Update UI

                            // Hide the progress bar
                            ((VidiomActivity) activity).finishedUploading(false);
                            ((VidiomActivity) activity)
                                    .createNotification(res.getString(R.string.upload_to_ftp_host_failed_));

                        }
                    }, 0);
                    return;
                }

                if (emailAddress != null && ftpHostName != null) {

                    // EmailSender through IR controlled gmail system.
                    SSLEmailSender sender = new SSLEmailSender(
                            activity.getString(R.string.automatic_email_username),
                            activity.getString(R.string.automatic_email_password)); // consider
                    // this
                    // public
                    // knowledge.
                    try {
                        sender.sendMail(activity.getString(R.string.vidiom_automatic_email), // subject.getText().toString(),
                                activity.getString(R.string.url_of_hosted_video_is_) + " " + ftpHostName, // body.getText().toString(),
                                activity.getString(R.string.automatic_email_from), // from.getText().toString(),
                                emailAddress // to.getText().toString()
                        );
                    } catch (Exception e) {
                        Log.e(TAG, e.getMessage(), e);
                    }
                }

                // Log record of this URL in POSTs table
                dbutils.creatHostDetailRecordwithNewVideoUploaded(sdrecord_id, ftpHostName, ftpHostName, "");

                mainapp.removeSDFileRecordIDfromUploadingTrack(sdrecord_id, TYPE_FTP);

                // Use the handler to execute a Runnable on the
                // main thread in order to have access to the
                // UI elements.
                handler.postDelayed(new Runnable() {
                    public void run() {
                        // Update UI

                        // Indicate back to calling activity the result!
                        // update uploadInProgress state also.

                        ((VidiomActivity) activity).finishedUploading(true);
                        ((VidiomActivity) activity)
                                .createNotification(res.getString(R.string.upload_to_ftp_host_succeeded_));

                    }
                }, 0);

            }
        });

        t.start();

        return t;
    }

    public void launchEmailIntentWithCurrentVideo(final Activity activity,
            final String latestVideoFile_absolutepath) {
        Log.d(TAG, "launchEmailIntentWithCurrentVideo starting");

        Intent i = new Intent(Intent.ACTION_SEND);
        i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        // XXX hardcoded video mimetype
        i.setType("video/mp4");
        i.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + latestVideoFile_absolutepath));
        activity.startActivity(i);
    }

    public void launchVideoPlayer(final Activity activity, final String moviePath) {

        try {
            Intent tostart = new Intent(Intent.ACTION_VIEW);
            tostart.setDataAndType(Uri.parse("file://" + moviePath), "video/*");
            activity.startActivity(tostart);
        } catch (android.content.ActivityNotFoundException e) {
            Log.e(TAG, " Cant start activity to show video!");

            e.printStackTrace();

            new AlertDialog.Builder(activity).setMessage(R.string.cant_show_video)
                    .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int whichButton) {

                        }
                    }).show();

            return;
        }

    }

    public File selectFilenameAndCreateFile(String filenameConventionPrefence, File base_folder) {
        // Video file name selection process
        String new_videofile_name = res.getString(R.string.defaultVideoFilenamePrefix);
        String file_ext_name = ".mp4";

        if (filenameConventionPrefence
                .compareTo(res.getString(R.string.filenameConventionDefaultPreference)) == 0) {
            // The default is by date
            SimpleDateFormat postFormater = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
            Calendar cal = Calendar.getInstance();
            Date now = cal.getTime();
            String newDateStr = postFormater.format(now);

            new_videofile_name += newDateStr + file_ext_name;

        } else {
            // Sequentially

            // look into database for this number
            int next_number = dbutils.getNextFilenameNumberAndIncrement();

            // XXX deal with -1 error condition

            new_videofile_name += next_number + file_ext_name;

        }

        File tempFile = new File(base_folder.getAbsolutePath(), new_videofile_name);
        return tempFile;
    }

    public boolean deleteVideo(String movieuri) {
        Log.d(TAG, "deleteVideo with " + movieuri);

        File tempFile = new File(movieuri);

        return tempFile.delete();

    }

    // youtube upload code from
    // from
    // http://code.google.com/p/ytd-android/source/browse/trunk/src/com/google/ytd/SubmitActivity.java
    // http://www.apache.org/licenses/LICENSE-2.0
    // Copyright 2010 Google License Apache
    //
    // Changed by Andy Nicholson

    //
    // developer docs
    // http://code.google.com/apis/youtube/2.0/developers_guide_protocol.html
    //

    public void asyncYouTubeUpload(final Activity activity, final File file, final Handler handler,
            final String emailAddress, final long sdrecord_id) {

        new Thread(new Runnable() {
            public void run() {
                Message msg = new Message();
                Bundle bundle = new Bundle();
                msg.setData(bundle);

                String videoId = null;
                int submitCount = 0;
                try {
                    while (submitCount <= MAX_RETRIES && videoId == null) {
                        try {
                            submitCount++;
                            videoId = startYouTubeUpload(activity, file, handler, emailAddress, sdrecord_id);
                            assert videoId != null;
                        } catch (Internal500ResumeException e500) { // TODO -
                            // this
                            // should
                            // not
                            // really
                            // happen
                            if (submitCount < MAX_RETRIES) {
                                Log.w(TAG, e500.getMessage());
                                Log.d(TAG, String.format("Upload retry :%d.", submitCount));
                            } else {
                                Log.d(TAG, "Giving up");
                                Log.e(TAG, e500.getMessage());
                                throw new IOException(e500.getMessage());
                            }
                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                    Log.e(TAG, "AsyncYouTubeUpload ERROR - finishing");
                    return;
                } catch (YouTubeAccountException e) {
                    e.printStackTrace();
                    Log.e(TAG, "AsyncYouTubeUpload ERROR - finishing");
                    return;
                } catch (SAXException e) {
                    e.printStackTrace();
                    Log.e(TAG, "AsyncYouTubeUpload ERROR - finishing");
                } catch (ParserConfigurationException e) {
                    e.printStackTrace();
                    Log.e(TAG, "AsyncYouTubeUpload ERROR - finishing");
                }

            }
        }).start();
    }

    static class YouTubeAccountException extends Exception {
        /**
         * 
         */
        private static final long serialVersionUID = 1L;

        public YouTubeAccountException(String msg) {
            super(msg);
        }
    }

    private String startYouTubeUpload(final Activity activity, File file, final Handler handler,
            final String emailAddress, final long sdrecord_id) throws IOException, YouTubeAccountException,
            SAXException, ParserConfigurationException, Internal500ResumeException {

        if (this.clientLoginToken == null) {
            // The stored gmail account is not linked to YouTube
            throw new YouTubeAccountException(this.youTubeName + " is not linked to a YouTube account.");
        }

        String[] strs = dbutils.getTitleAndDescriptionFromID(new String[] { Long.toString(sdrecord_id) });
        // add our branding to the description.
        String uploadUrl = uploadMetaData(activity, handler, file.getAbsolutePath(), strs[0], strs[1], true,
                sdrecord_id);

        Log.d(TAG, "uploadUrl=" + uploadUrl + " youtube account name is " + this.youTubeName);
        Log.d(TAG, String.format("Client token : %s ", this.clientLoginToken));

        this.currentFileSize = file.length();
        this.totalBytesUploaded = 0;
        this.numberOfRetries = 0;

        int uploadChunk = 1024 * 1024 * 3; // 3MB

        int start = 0;
        int end = -1;

        String videoId = null;
        double fileSize = this.currentFileSize;
        while (fileSize > 0) {
            if (fileSize - uploadChunk > 0) {
                end = start + uploadChunk - 1;
            } else {
                end = start + (int) fileSize - 1;
            }
            Log.d(TAG, String.format("start=%s end=%s total=%s", start, end, file.length()));
            try {
                videoId = gdataUpload(file, uploadUrl, start, end);
                fileSize -= uploadChunk;
                start = end + 1;
                this.numberOfRetries = 0; // clear this counter as we had a
                // successful upload
            } catch (IOException e) {
                Log.d(TAG, "Error during upload : " + e.getMessage());
                ResumeInfo resumeInfo = null;
                do {
                    if (!shouldResume()) {
                        Log.d(TAG, String.format("Giving up uploading '%s'.", uploadUrl));
                        throw e;
                    }
                    try {
                        resumeInfo = resumeFileUpload(uploadUrl);
                    } catch (IOException re) {
                        // ignore
                        Log.d(TAG, String.format("Failed retry attempt of : %s due to: '%s'.", uploadUrl,
                                re.getMessage()));
                    }
                } while (resumeInfo == null);
                Log.d(TAG, String.format("Resuming stalled upload to: %s.", uploadUrl));
                if (resumeInfo.videoId != null) { // upload actually complted
                    // despite the exception
                    videoId = resumeInfo.videoId;
                    Log.d(TAG, String.format("No need to resume video ID '%s'.", videoId));
                    break;
                } else {
                    int nextByteToUpload = resumeInfo.nextByteToUpload;
                    Log.d(TAG, String.format("Next byte to upload is '%d'.", nextByteToUpload));
                    this.totalBytesUploaded = nextByteToUpload; // possibly
                    // rolling back
                    // the
                    // previously
                    // saved value
                    fileSize = this.currentFileSize - nextByteToUpload;
                    start = nextByteToUpload;
                }
            }
        }

        if (videoId != null) {

            if (emailAddress != null) {

                // EmailSender through IR controlled mail system.
                SSLEmailSender sender = new SSLEmailSender(activity.getString(R.string.automatic_email_username),
                        activity.getString(R.string.automatic_email_password)); // consider
                // this
                // public
                // knowledge.
                try {
                    sender.sendMail(activity.getString(R.string.vidiom_automatic_email), // subject.getText().toString(),
                            activity.getString(R.string.url_of_hosted_video_is_) + " " + YOUTUBE_PLAYER_URL
                                    + videoId, // body.getText().toString(),
                            activity.getString(R.string.automatic_email_from), // from.getText().toString(),
                            emailAddress // to.getText().toString()
                    );
                } catch (Exception e) {
                    Log.e(TAG, e.getMessage(), e);
                }
            }

            // Log record of this URL in POSTs table
            dbutils.creatHostDetailRecordwithNewVideoUploaded(sdrecord_id, uploadUrl, YOUTUBE_PLAYER_URL + videoId,
                    "");

            mainapp.removeSDFileRecordIDfromUploadingTrack(sdrecord_id, TYPE_YT);

            // Use the handler to execute a Runnable on the
            // main thread in order to have access to the
            // UI elements.
            handler.postDelayed(new Runnable() {
                public void run() {
                    // Update UI

                    // Indicate back to calling activity the result!
                    // update uploadInProgress state also.

                    ((VidiomActivity) activity).finishedUploading(true);
                    ((VidiomActivity) activity)
                            .createNotification(res.getString(R.string.upload_to_youtube_host_succeeded_));

                }
            }, 0);

            return videoId;
        }

        return null;
    }

    private String uploadMetaData(final Activity activity, final Handler handler, String filePath, String title,
            String description, boolean retry, long sdrecord_id) throws IOException {
        String uploadUrl = INITIAL_UPLOAD_URL;

        HttpURLConnection urlConnection = getGDataUrlConnection(uploadUrl);
        urlConnection.setRequestMethod("POST");
        urlConnection.setDoOutput(true);
        urlConnection.setRequestProperty("Content-Type", "application/atom+xml");
        // urlConnection.setRequestProperty("Content-Length", newValue);
        urlConnection.setRequestProperty("Slug", filePath);
        String atomData = null;

        String category = DEFAULT_VIDEO_CATEGORY;
        this.tags = DEFAULT_VIDEO_TAGS;

        String template = readFile(activity, R.raw.gdata).toString();

        // Workarounds for corner cases. Youtube doesnt like empty titles
        if (title == null || title.length() == 0) {
            title = "Untitled";
        }
        if (description == null || description.length() == 0) {
            description = "No description";
        }

        // Check user preference to see if YouTube videos should be private by
        // default.
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity.getBaseContext());
        Boolean ytPrivate = prefs.getBoolean("defaultYouTubePrivatePreference", true);

        String private_or_not = "<yt:private />";
        if (!ytPrivate) {
            private_or_not = "";
        }

        atomData = String.format(template, title, description, category, this.tags, private_or_not);

        OutputStreamWriter outStreamWriter = null;
        int responseCode = -1;

        try {
            outStreamWriter = new OutputStreamWriter(urlConnection.getOutputStream());
            outStreamWriter.write(atomData);
            outStreamWriter.close();

            /*
             * urlConnection.connect(); InputStream is =
             * urlConnection.getInputStream(); BufferedReader in = new
             * BufferedReader(new InputStreamReader(is)); String inputLine;
             * 
             * while ((inputLine = in.readLine()) != null) {
             * Log.d(TAG,inputLine); } in.close();
             */

            responseCode = urlConnection.getResponseCode();

            // ERROR LOGGING
            InputStream is = urlConnection.getErrorStream();
            if (is != null) {
                Log.e(TAG, " Error stream from Youtube available!");
                BufferedReader in = new BufferedReader(new InputStreamReader(is));
                String inputLine;

                while ((inputLine = in.readLine()) != null) {
                    Log.d(TAG, inputLine);
                }
                in.close();

                Map<String, List<String>> hfs = urlConnection.getHeaderFields();
                for (Entry<String, List<String>> hf : hfs.entrySet()) {
                    Log.d(TAG, " entry : " + hf.getKey());
                    List<String> vals = hf.getValue();
                    for (String s : vals) {
                        Log.d(TAG, "vals:" + s);
                    }
                }
            }

        } catch (IOException e) {
            //
            // Catch IO Exceptions here, like UnknownHostException, so we can
            // detect network failures, and send a notification
            //
            Log.d(TAG, " Error occured in uploadMetaData! ");
            e.printStackTrace();
            responseCode = -1;
            outStreamWriter = null;

            mainapp.removeSDFileRecordIDfromUploadingTrack(sdrecord_id, TYPE_YT);

            // Use the handler to execute a Runnable on the
            // main thread in order to have access to the
            // UI elements.
            handler.postDelayed(new Runnable() {
                public void run() {
                    // Update UI

                    // Indicate back to calling activity the result!
                    // update uploadInProgress state also.

                    ((VidiomActivity) activity).finishedUploading(false);
                    ((VidiomActivity) activity)
                            .createNotification(res.getString(R.string.upload_to_youtube_host_failed_));

                }
            }, 0);

            // forward it on!
            throw e;
        }

        if (responseCode < 200 || responseCode >= 300) {
            // The response code is 40X
            if ((responseCode + "").startsWith("4") && retry) {
                Log.d(TAG, "retrying to fetch auth token for " + youTubeName);
                this.clientLoginToken = authorizer.getFreshAuthToken(youTubeName, clientLoginToken);
                // Try again with fresh token
                return uploadMetaData(activity, handler, filePath, title, description, false, sdrecord_id);
            } else {

                mainapp.removeSDFileRecordIDfromUploadingTrack(sdrecord_id, TYPE_YT);

                // Probably not authorised!

                // Need to setup a Youtube account.

                // Use the handler to execute a Runnable on the
                // main thread in order to have access to the
                // UI elements.
                handler.postDelayed(new Runnable() {
                    public void run() {
                        // Update UI

                        // Indicate back to calling activity the result!
                        // update uploadInProgress state also.

                        ((VidiomActivity) activity).finishedUploading(false);
                        ((VidiomActivity) activity)
                                .createNotification(res.getString(R.string.upload_to_youtube_host_failed_));

                    }
                }, 0);

                throw new IOException(String.format("response code='%s' (code %d)" + " for %s",
                        urlConnection.getResponseMessage(), responseCode, urlConnection.getURL()));

            }
        }

        return urlConnection.getHeaderField("Location");
    }

    private String gdataUpload(File file, String uploadUrl, int start, int end) throws IOException {
        int chunk = end - start + 1;
        int bufferSize = 1024;
        byte[] buffer = new byte[bufferSize];
        FileInputStream fileStream = new FileInputStream(file);

        HttpURLConnection urlConnection = getGDataUrlConnection(uploadUrl);
        // some mobile proxies do not support PUT, using X-HTTP-Method-Override
        // to get around this problem
        if (isFirstRequest()) {
            Log.d(TAG, String.format("Uploaded %d bytes so far, using POST method.", (int) totalBytesUploaded));
            urlConnection.setRequestMethod("POST");
        } else {
            urlConnection.setRequestMethod("POST");
            urlConnection.setRequestProperty("X-HTTP-Method-Override", "PUT");
            Log.d(TAG, String.format("Uploaded %d bytes so far, using POST with X-HTTP-Method-Override PUT method.",
                    (int) totalBytesUploaded));
        }
        urlConnection.setDoOutput(true);
        urlConnection.setFixedLengthStreamingMode(chunk);
        // /XXX hardcoded video mimetype
        urlConnection.setRequestProperty("Content-Type", "video/mp4");
        urlConnection.setRequestProperty("Content-Range",
                String.format("bytes %d-%d/%d", start, end, file.length()));
        Log.d(TAG, urlConnection.getRequestProperty("Content-Range"));

        OutputStream outStreamWriter = urlConnection.getOutputStream();

        fileStream.skip(start);

        int bytesRead;
        int totalRead = 0;
        while ((bytesRead = fileStream.read(buffer, 0, bufferSize)) != -1) {
            outStreamWriter.write(buffer, 0, bytesRead);
            totalRead += bytesRead;
            this.totalBytesUploaded += bytesRead;

            // double percent = (totalBytesUploaded / currentFileSize) * 99;

            /*
             * Log.d(TAG, String.format(
             * "fileSize=%f totalBytesUploaded=%f percent=%f", currentFileSize,
             * totalBytesUploaded, percent));
             */

            if (totalRead == (end - start + 1)) {
                break;
            }
        }

        outStreamWriter.close();

        int responseCode = urlConnection.getResponseCode();

        Log.d(TAG, "responseCode=" + responseCode);
        Log.d(TAG, "responseMessage=" + urlConnection.getResponseMessage());

        try {
            if (responseCode == 201) {
                String videoId = parseVideoId(urlConnection.getInputStream());

                Log.i(TAG, "Youtube video submitted - new video id is " + videoId);

                // 100% finished here.

                // dialog.setProgress(100);

                return videoId;
            } else if (responseCode == 200) {
                Set<String> keySet = urlConnection.getHeaderFields().keySet();
                String keys = urlConnection.getHeaderFields().keySet().toString();
                Log.d(TAG, String.format("Headers keys %s.", keys));
                for (String key : keySet) {
                    Log.d(TAG, String.format("Header key %s value %s.", key, urlConnection.getHeaderField(key)));
                }
                Log.w(TAG, "Received 200 response during resumable uploading");
                throw new IOException(String.format("Unexpected response code : responseCode=%d responseMessage=%s",
                        responseCode, urlConnection.getResponseMessage()));
            } else {
                if ((responseCode + "").startsWith("5")) {
                    String error = String.format("responseCode=%d responseMessage=%s", responseCode,
                            urlConnection.getResponseMessage());
                    Log.w(TAG, error);
                    // TODO - this exception will trigger retry mechanism to
                    // kick in
                    // TODO - even though it should not, consider introducing a
                    // new type so
                    // TODO - resume does not kick in upon 5xx
                    throw new IOException(error);
                } else if (responseCode == 308) {
                    // OK, the chunk completed successfully
                    Log.d(TAG, String.format("responseCode=%d responseMessage=%s", responseCode,
                            urlConnection.getResponseMessage()));
                } else {
                    // TODO - this case is not handled properly yet
                    Log.w(TAG, String.format("Unexpected return code : %d %s while uploading :%s", responseCode,
                            urlConnection.getResponseMessage(), uploadUrl));
                }
            }
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        }

        return null;
    }

    public boolean isFirstRequest() {
        return totalBytesUploaded == 0;
    }

    private ResumeInfo resumeFileUpload(String uploadUrl)
            throws IOException, ParserConfigurationException, SAXException, Internal500ResumeException {
        HttpURLConnection urlConnection = getGDataUrlConnection(uploadUrl);
        urlConnection.setRequestProperty("Content-Range", "bytes */*");
        urlConnection.setRequestMethod("POST");
        urlConnection.setRequestProperty("X-HTTP-Method-Override", "PUT");
        urlConnection.setFixedLengthStreamingMode(0);

        HttpURLConnection.setFollowRedirects(false);

        urlConnection.connect();
        int responseCode = urlConnection.getResponseCode();

        if (responseCode >= 300 && responseCode < 400) {
            int nextByteToUpload;
            String range = urlConnection.getHeaderField("Range");
            if (range == null) {
                Log.d(TAG, String.format("PUT to %s did not return 'Range' header.", uploadUrl));
                nextByteToUpload = 0;
            } else {
                Log.d(TAG, String.format("Range header is '%s'.", range));
                String[] parts = range.split("-");
                if (parts.length > 1) {
                    nextByteToUpload = Integer.parseInt(parts[1]) + 1;
                } else {
                    nextByteToUpload = 0;
                }
            }
            return new ResumeInfo(nextByteToUpload);
        } else if (responseCode >= 200 && responseCode < 300) {
            return new ResumeInfo(parseVideoId(urlConnection.getInputStream()));
        } else if (responseCode == 500) {
            // TODO this is a workaround for current problems with resuming
            // uploads while switching transport (Wifi->EDGE)
            throw new Internal500ResumeException(
                    String.format("Unexpected response for PUT to %s: %s " + "(code %d)", uploadUrl,
                            urlConnection.getResponseMessage(), responseCode));
        } else {
            throw new IOException(String.format("Unexpected response for PUT to %s: %s " + "(code %d)", uploadUrl,
                    urlConnection.getResponseMessage(), responseCode));
        }
    }

    //
    // This process fetches a google-youtube auth token, linked from a google
    // email account
    // if successfully, it launches the async upload.
    //

    private boolean shouldResume() {
        this.numberOfRetries++;
        if (this.numberOfRetries > MAX_RETRIES) {
            return false;
        }
        try {
            int sleepSeconds = (int) Math.pow(BACKOFF, this.numberOfRetries);
            Log.d(TAG, String.format("Zzzzz for : %d sec.", sleepSeconds));
            Thread.currentThread().sleep(sleepSeconds * 1000);
            Log.d(TAG, String.format("Zzzzz for : %d sec done.", sleepSeconds));
        } catch (InterruptedException se) {
            se.printStackTrace();
            return false;
        }
        return true;
    }

    private String parseVideoId(InputStream atomDataStream)
            throws ParserConfigurationException, SAXException, IOException {
        DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
        Document doc = docBuilder.parse(atomDataStream);

        NodeList nodes = doc.getElementsByTagNameNS("*", "*");
        for (int i = 0; i < nodes.getLength(); i++) {
            Node node = nodes.item(i);
            String nodeName = node.getNodeName();
            String val_print;
            if (node.getFirstChild() != null) {
                val_print = node.getFirstChild().getNodeValue();
            } else {
                val_print = "null";
            }

            Log.d(TAG, " node name " + nodeName + " val : " + val_print);
            if (nodeName != null && nodeName.equals("yt:videoid")) {
                return node.getFirstChild().getNodeValue();
            }
        }
        return null;
    }

    private HttpURLConnection getGDataUrlConnection(String urlString) throws IOException {
        URL url = new URL(urlString);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestProperty("Authorization", String.format("GoogleLogin auth=\"%s\"", clientLoginToken));
        connection.setRequestProperty("GData-Version", "2");
        connection.setRequestProperty("X-GData-Key",
                String.format("key=%s", res.getString(R.string.youtube_dev_key)));
        return connection;
    }

    public void getYouTubeAuthTokenWithPermissionAndUpload(final Activity activity, String accountName,
            final String path, final Handler handler, final String emailAddress, final long sdrecord_id) {

        // Make the progress bar view visible.
        ((VidiomActivity) activity).startedUploading(PublishingUtils.TYPE_YT);

        this.youTubeName = accountName;

        this.authorizer = new GlsAuthorizer.GlsAuthorizerFactory().getAuthorizer(activity,
                GlsAuthorizer.YOUTUBE_AUTH_TOKEN_TYPE);

        this.authorizer.fetchAuthToken(accountName, activity, new AuthorizationListener<String>() {
            public void onCanceled() {

                Log.d(TAG, " Cancelled in fetchAuthToken! ");

            }

            public void onError(Exception e) {

                Log.d(TAG, " Error in fetchAuthToken! ");

                mainapp.removeSDFileRecordIDfromUploadingTrack(sdrecord_id, TYPE_YT);

                // Use the handler to execute a Runnable on the
                // main thread in order to have access to the
                // UI elements.
                handler.postDelayed(new Runnable() {
                    public void run() {
                        // Update UI

                        // Indicate back to calling activity the result!
                        // update uploadInProgress state also.

                        ((VidiomActivity) activity).finishedUploading(false);
                        ((VidiomActivity) activity)
                                .createNotification(res.getString(R.string.upload_to_youtube_host_failed_));

                    }
                }, 0);

            }

            public void onSuccess(String result) {
                PublishingUtils.this.clientLoginToken = result;
                File file = new File(path);
                // Launch Async YouTube video upload.
                asyncYouTubeUpload(activity, file, handler, emailAddress, sdrecord_id);
            }
        });
    }

    class ResumeInfo {
        int nextByteToUpload;
        String videoId;

        ResumeInfo(int nextByteToUpload) {
            this.nextByteToUpload = nextByteToUpload;
        }

        ResumeInfo(String videoId) {
            this.videoId = videoId;
        }
    }

    /**
     * Need this for now to trigger entire upload transaction retry
     */
    class Internal500ResumeException extends Exception {
        /**
         * 
         */
        private static final long serialVersionUID = 1L;

        Internal500ResumeException(String message) {
            super(message);
        }
    }

    public static CharSequence readFile(Activity activity, int id) {
        BufferedReader in = null;
        try {
            in = new BufferedReader(new InputStreamReader(activity.getResources().openRawResource(id)));
            String line;
            StringBuilder buffer = new StringBuilder();
            while ((line = in.readLine()) != null) {
                buffer.append(line).append('\n');
            }
            // Chomp the last newline
            buffer.deleteCharAt(buffer.length() - 1);
            return buffer;
        } catch (IOException e) {
            return "";
        } finally {
            closeStream(in);
        }
    }

    /**
     * Closes the specified stream.
     * 
     * @param stream
     *            The stream to close.
     */
    private static void closeStream(Closeable stream) {
        if (stream != null) {
            try {
                stream.close();
            } catch (IOException e) {
                // Ignore
            }
        }
    }

}