3

I'm trying to share a youtube link from within my app using the following flow:

1) Select a video from within my app using a gallery pick intent.

2) Send the video to the Youtube app using another intent, and upload it to Youtube there.

3) Get the newly uploaded video link from the Youtube app and return it to my activity via an Activity Result.

Unfortunately i am stuck at step 3 as i couldn't find any way to launch the Youtube Upload activity for result or get any link from it, and as far as i have seen so far there doesn't seem to be any way to return the upload result to the calling app.

I am aware that the Youtube Api exists, but am trying to avoid using it due to the associated costs that may appear from over usage.

If anyone has any insight as to how this could be done it would be greatly appreciated.

Rakatan
  • 451
  • 4
  • 17
  • did u solve it ? – Manohar Aug 21 '17 at 09:12
  • I've found that there is no real way to do this reliably, and so I prompt the user to copy the youtube link after uploading the video. When returning to the app I automatically copy the contents from the clipboard into the UI and hope that it's the correct link. – Rakatan Aug 21 '17 at 12:19
  • i just found solution , we can get video id after successful uploading of video `Video video = videoInsert.execute();` now we can get id by using `video.getId();` . Append this Id to `https://www.youtube.com/watch?v=` That is the full link – Manohar Aug 21 '17 at 12:28
  • Can you provide more details about what type videoInsert actually is? Maybe as an answer to this question? I'll try it out and accept it if it works – Rakatan Aug 21 '17 at 12:30
  • Ok , i will post what ever i did till now – Manohar Aug 21 '17 at 12:38
  • did you find solution? – Vadym Jan 18 '18 at 11:50

1 Answers1

0

Create class PreferenceManager.java

public class PreferenceManager {
     static String accountNamem;

    public  static String getAccountName() {
        return accountNamem;
    }

    public static void setAccountName (String accountName)  {
        accountNamem = accountName;
    }
}

create fragment NewUpload.java

import android.accounts.AccountManager;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.Toast;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.common.api.Result;
import com.google.api.client.extensions.android.http.AndroidHttp;
import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential;
import com.google.api.client.googleapis.extensions.android.gms.auth.GooglePlayServicesAvailabilityIOException;
import com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException;
import com.google.api.client.googleapis.media.MediaHttpUploader;
import com.google.api.client.googleapis.media.MediaHttpUploaderProgressListener;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.InputStreamContent;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.services.youtube.YouTube;
import com.google.api.services.youtube.YouTubeScopes;
import com.google.api.services.youtube.model.Video;
import com.google.api.services.youtube.model.VideoSnippet;
import com.google.api.services.youtube.model.VideoStatus;
import com.google.common.collect.Lists;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import in.eightfolds.youtubeupload.Utils.PreferenceManager;

/**
 * Created by Sagar on 21/08/2017.
 */

public class NewUpload extends Fragment{

    private static GoogleAccountCredential credential;
    private static final HttpTransport transport = AndroidHttp.newCompatibleTransport();
    private static final JsonFactory jsonFactory = new GsonFactory();
    public YouTube youtube;
    List<String> scopes = Lists.newArrayList(YouTubeScopes.YOUTUBE_UPLOAD);
    private static String VIDEO_FILE_FORMAT = "video/*";

    static final int REQUEST_GOOGLE_PLAY_SERVICES = 0;
    static final int REQUEST_AUTHORIZATION = 1;
    static final int REQUEST_ACCOUNT_PICKER = 2;
    static Context context;


    Button btn_upload;
    private String TAG = "Tag";
    private int PLAY_SERVICES_RESOLUTION_REQUEST = 1037;


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        context = getActivity();

        return inflater.inflate(R.layout.fragment_upload, container, false);
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        btn_upload = view.findViewById(R.id.btn_upload);

    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);


        try {
            credential = googleAccountCredential(scopes);
        } catch (Exception e) {
            e.printStackTrace();
        }
        youtube = new YouTube.Builder(transport, jsonFactory, credential)
                .setApplicationName("MyAppName")
                .build();

       btn_upload.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (hasPlayServices()) {
                    uploadYouTubeVideos();
                    Toast.makeText(getActivity(), "clicked", Toast.LENGTH_SHORT).show();
                }
                else {
                    Toast.makeText(getActivity(), "No Play Services", Toast.LENGTH_SHORT).show();
                }
            }
        });
    }


    private static GoogleAccountCredential googleAccountCredential(List<String> scopes) throws Exception {

        credential = GoogleAccountCredential.usingOAuth2(context, scopes)
                .setSelectedAccountName(PreferenceManager.getAccountName());
        return credential;
    }

    private void chooseAccount() {
        startActivityForResult(credential.newChooseAccountIntent(), REQUEST_ACCOUNT_PICKER);
    }


    public void uploadYouTubeVideos() {
        if (credential.getSelectedAccountName() == null) {
            chooseAccount();
        } else {


            File videoFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/video.mp4");
            YouTube.Videos.Insert videoInsert = prepareUpload(videoFile);
            new VideoUploadAsyncTask().execute(videoInsert);
        }
    }


    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch (requestCode) {
            case REQUEST_AUTHORIZATION:
                if (resultCode == Activity.RESULT_OK) {
                    uploadYouTubeVideos();
                } else {
                    chooseAccount();
                }
                break;
            case REQUEST_ACCOUNT_PICKER:
                if (resultCode == Activity.RESULT_OK && data != null && data.getExtras() != null) {
                    String accountName = data.getExtras().getString(AccountManager.KEY_ACCOUNT_NAME);
                    if (accountName != null) {
                        credential.setSelectedAccountName(accountName);
                        PreferenceManager.setAccountName(accountName);

                        uploadYouTubeVideos();
                    }
                }
                break;

        }
    }


    public YouTube.Videos.Insert prepareUpload(File videoFile) {
        try {
            // Add extra information to the video before uploading.
            Video videoObjectDefiningMetadata = new Video();

            // Set the video to public (default).
            VideoStatus status = new VideoStatus();
            status.setPrivacyStatus("public");
            videoObjectDefiningMetadata.setStatus(status);

            // We set a majority of the metadata with the VideoSnippet object.
            VideoSnippet snippet = new VideoSnippet();

            // Video file name.
            snippet.setTitle(videoFile.getName());
            snippet.setDescription("Test description");

            // Set keywords.
            List<String> tags = new ArrayList<String>();
            tags.add("test");
            snippet.setTags(tags);

            // Set completed snippet to the video object.
            videoObjectDefiningMetadata.setSnippet(snippet);

            InputStreamContent mediaContent = new InputStreamContent(
                    VIDEO_FILE_FORMAT, new BufferedInputStream(new FileInputStream(videoFile)));
            mediaContent.setLength(videoFile.length());

            /*
             * The upload command includes: 1. Information we want returned after file is successfully
             * uploaded. 2. Metadata we want associated with the uploaded video. 3. Video file itself.
             */
            YouTube.Videos.Insert videoInsert = youtube.videos()
                    .insert("snippet,statistics,status", videoObjectDefiningMetadata, mediaContent);


            // Set the upload type and add event listener.
            MediaHttpUploader uploader = videoInsert.getMediaHttpUploader();

            /*
             * Sets whether direct media upload is enabled or disabled. True = whole media content is
             * uploaded in a single request. False (default) = resumable media upload protocol to upload
             * in data chunks.
             */
            uploader.setDirectUploadEnabled(false);

            MediaHttpUploaderProgressListener progressListener = new MediaHttpUploaderProgressListener() {
                public void progressChanged(MediaHttpUploader uploader) throws IOException {
                    switch (uploader.getUploadState()) {
                        case INITIATION_STARTED:
                            Log.d(TAG, "Upload file: Initiation Started");
                            break;
                        case INITIATION_COMPLETE:
                            Log.d(TAG, "Upload file: Initiation Completed");
                            break;
                        case MEDIA_IN_PROGRESS:
                            Log.d(TAG, "Upload file: Upload in progress");
                            Log.d(TAG, "Upload file: Upload percentage: " + uploader.getProgress());
                            break;
                        case MEDIA_COMPLETE:
                            Log.d(TAG, "Upload file: Upload Completed!");
                            break;
                        case NOT_STARTED:
                            Log.d(TAG, "Upload file: Upload Not Started!");
                            break;
                    }
                }
            };
            uploader.setProgressListener(progressListener);

            return videoInsert;
        } catch (FileNotFoundException e) {
            Log.e(TAG, "File not found: " + e.getMessage());
            return null;
        } catch (IOException e) {
            Log.e(TAG, "IOException: " + e.getMessage());
            return null;
        }
    }


    void showGooglePlayServicesAvailabilityErrorDialog(final int connectionStatusCode) {
        getActivity().runOnUiThread(new Runnable() {
            public void run() {
                Dialog dialog =
                        GooglePlayServicesUtil.getErrorDialog(connectionStatusCode, getActivity(),
                                REQUEST_GOOGLE_PLAY_SERVICES);
                dialog.show();
            }
        });
    }



    public class VideoUploadAsyncTask extends AsyncTask<YouTube.Videos.Insert, Void, Void> {
        @Override
        protected Void doInBackground(YouTube.Videos.Insert... inserts) {
            YouTube.Videos.Insert videoInsert = inserts[0];
            try {
                Video returnVideo = videoInsert.execute();

                returnVideo.getId();
                Log.i("Video Id", "" + returnVideo.getId());   // ----> This is the video Id . 
                 Toast.makeText(getActivity(), ""+"https://www.youtube.com/watch?v="+returnVideo.getId(), Toast.LENGTH_SHORT).show();
            Log.i("Video Id1", "" + returnVideo.getFileDetails());
            Log.i("Video Url", "" + "https://www.youtube.com/watch?v="+returnVideo.getId());

            } catch (final GooglePlayServicesAvailabilityIOException availabilityException) {
                showGooglePlayServicesAvailabilityErrorDialog(
                        availabilityException.getConnectionStatusCode());
            } catch (UserRecoverableAuthIOException userRecoverableException) {
                startActivityForResult(
                        userRecoverableException.getIntent(), NewUpload.REQUEST_AUTHORIZATION);
            } catch (IOException e) {
                Log.e(TAG, "IOException: " + e.getMessage());
            }


            return null;
        }
    }


    private boolean hasPlayServices() {
        GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance();
        int resultCode = apiAvailability.isGooglePlayServicesAvailable(getActivity());
        if (resultCode != ConnectionResult.SUCCESS) {
            if (apiAvailability.isUserResolvableError(resultCode)) {
                apiAvailability.getErrorDialog(getActivity(), resultCode, PLAY_SERVICES_RESOLUTION_REQUEST)
                        .show();
            } else {
                Log.i(TAG, "This device is not supported.");
//                finish();
                Toast.makeText(getActivity(), "Play services not available", Toast.LENGTH_SHORT).show();
            }
            return false;
        }
        return true;
    }

}

Call this fragment from activity using

   NewUpload upload=new NewUpload();
    getSupportFragmentManager()
            .beginTransaction()
            .add(R.id.relative_main,upload) // give your container Id here
            .commit();

for above example to work add read storage permission . Keep a video in internal memory with name "video.mp4" -->This video will be uploaded to the choosen account

you can change this logic in uploadYouTubeVideos() method inside fragment

for layout keep 1 button with id btn_upload inside fragment_upload

use this dependency for gsonfactory

    compile 'com.google.http-client:google-http-client-gson:1.19.0'
Manohar
  • 22,116
  • 9
  • 108
  • 144
  • Is this by any chance based on the Youtube Data API? – Rakatan Aug 21 '17 at 13:25
  • i am not sure i copied most parts from [here](https://stackoverflow.com/questions/18022444/youtube-api-3-upload-video-access-not-configured-android) – Manohar Aug 21 '17 at 13:33
  • inside `VideoUploadAsyncTask` we are getting the url – Manohar Aug 21 '17 at 13:36
  • It seems that it does indeed. Quoted from the question you linked: "I am working on an Android app that records video and allows the user to upload it directly to YouTube using the YouTube Data API v3." Unfortunately this is not an option for me. Using the Youtube Data API can incur operational costs over a certain request threshold, which is exactly what i was hoping to avoid by using the integrated Youtube App – Rakatan Aug 21 '17 at 14:22