Last active
April 24, 2018 09:42
-
-
Save Redman1037/24274d64e2f575c01ad967519534a639 to your computer and use it in GitHub Desktop.
Youtube Upload Android
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8"?> | |
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | |
xmlns:tools="http://schemas.android.com/tools" | |
android:layout_width="match_parent" | |
android:layout_height="match_parent" | |
android:gravity="center" | |
android:orientation="vertical" | |
tools:context=".MainActivity" > | |
<Button | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:id="@+id/mCallApiButton" | |
android:text="Upload Video " | |
android:layout_marginBottom="20dp"/> | |
<TextView | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
android:layout_marginBottom="20dp" | |
android:text="Upload Video" | |
android:id="@+id/tv_outputText"/> | |
</LinearLayout> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8"?> | |
<manifest xmlns:android="http://schemas.android.com/apk/res/android" | |
package="in.eightfolds.youtubetestapplication"> | |
<uses-permission android:name="android.permission.INTERNET" /> | |
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> | |
<uses-permission android:name="android.permission.GET_ACCOUNTS" /> | |
<uses-permission android:name="android.permission.CAMERA"/> | |
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> | |
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> | |
<application | |
android:allowBackup="true" | |
android:icon="@mipmap/ic_launcher" | |
android:label="@string/app_name" | |
android:roundIcon="@mipmap/ic_launcher_round" | |
android:supportsRtl="true" | |
android:theme="@style/AppTheme"> | |
<activity android:name=".MainActivity"> | |
<intent-filter> | |
<action android:name="android.intent.action.MAIN" /> | |
<category android:name="android.intent.category.LAUNCHER" /> | |
</intent-filter> | |
</activity> | |
</application> | |
</manifest> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
apply plugin: 'com.android.application' | |
apply plugin: 'kotlin-android' | |
apply plugin: 'kotlin-android-extensions' | |
android { | |
compileSdkVersion 27 | |
defaultConfig { | |
applicationId "in.eightfolds.youtubetestapplication" | |
minSdkVersion 16 | |
targetSdkVersion 27 | |
versionCode 1 | |
versionName "1.0" | |
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" | |
} | |
buildTypes { | |
release { | |
minifyEnabled false | |
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' | |
} | |
} | |
} | |
dependencies { | |
implementation fileTree(dir: 'libs', include: ['*.jar']) | |
implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" | |
implementation 'com.android.support:appcompat-v7:27.1.1' | |
implementation 'com.android.support.constraint:constraint-layout:1.1.0' | |
testImplementation 'junit:junit:4.12' | |
androidTestImplementation 'com.android.support.test:runner:1.0.1' | |
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' | |
compile 'com.google.apis:google-api-services-youtube:v3-rev195-1.23.0' | |
compile 'com.nabinbhandari.android:permissions:3.5' | |
compile 'com.google.android.gms:play-services-auth:15.0.0' | |
compile('com.google.api-client:google-api-client-android:1.23.0') { | |
exclude group: 'org.apache.httpcomponents' | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package in.eightfolds.youtubetestapplication; | |
import android.Manifest; | |
import android.accounts.AccountManager; | |
import android.app.Activity; | |
import android.app.Dialog; | |
import android.app.ProgressDialog; | |
import android.content.Context; | |
import android.content.Intent; | |
import android.content.SharedPreferences; | |
import android.content.pm.PackageManager; | |
import android.content.pm.ResolveInfo; | |
import android.database.Cursor; | |
import android.net.ConnectivityManager; | |
import android.net.NetworkInfo; | |
import android.net.Uri; | |
import android.os.AsyncTask; | |
import android.os.Bundle; | |
import android.provider.MediaStore; | |
import android.util.Log; | |
import android.view.View; | |
import android.widget.Button; | |
import android.widget.TextView; | |
import android.widget.Toast; | |
import com.google.android.gms.common.ConnectionResult; | |
import com.google.android.gms.common.GoogleApiAvailability; | |
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.AbstractInputStreamContent; | |
import com.google.api.client.http.HttpRequest; | |
import com.google.api.client.http.HttpRequestInitializer; | |
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.jackson2.JacksonFactory; | |
import com.google.api.client.util.ExponentialBackOff; | |
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.nabinbhandari.android.permissions.PermissionHandler; | |
import com.nabinbhandari.android.permissions.Permissions; | |
import java.io.BufferedInputStream; | |
import java.io.File; | |
import java.io.FileInputStream; | |
import java.io.FileNotFoundException; | |
import java.io.IOException; | |
import java.util.Arrays; | |
import java.util.List; | |
public class MainActivity extends Activity { | |
GoogleAccountCredential mCredential; | |
private TextView mOutputText; | |
private Button mCallApiButton; | |
private static final String TAG = "MainActivity"; | |
private static final int CAPTURE_RETURN = 1; | |
private static final int GALLERY_RETURN = 2; | |
static final int REQUEST_ACCOUNT_PICKER = 1000; | |
static final int REQUEST_AUTHORIZATION = 1001; | |
static final int REQUEST_GOOGLE_PLAY_SERVICES = 1002; | |
private static final String PREF_ACCOUNT_NAME = "accountName"; | |
private static final String[] SCOPES = {YouTubeScopes.YOUTUBE_READONLY, YouTubeScopes.YOUTUBE_UPLOAD}; | |
/** | |
* Create the main activity. | |
* | |
* @param savedInstanceState previously saved instance data. | |
*/ | |
@Override | |
protected void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
setContentView(R.layout.activity_main); | |
mCallApiButton = findViewById(R.id.mCallApiButton); | |
mOutputText = findViewById(R.id.tv_outputText); | |
// Initialize credentials and service object. | |
mCredential = GoogleAccountCredential.usingOAuth2( | |
getApplicationContext(), Arrays.asList(SCOPES)) | |
.setBackOff(new ExponentialBackOff()); | |
mCallApiButton.setOnClickListener(new View.OnClickListener() { | |
@Override | |
public void onClick(View v) { | |
Permissions.check(MainActivity.this, new String[]{Manifest.permission.GET_ACCOUNTS, | |
Manifest.permission.READ_EXTERNAL_STORAGE}, | |
"Accounts and Storage permissions are required ", new Permissions.Options() | |
.setSettingsDialogTitle("Warning!").setRationaleDialogTitle("Info"), | |
new PermissionHandler() { | |
@Override | |
public void onGranted() { | |
mCallApiButton.setEnabled(false); | |
mOutputText.setText(""); | |
getResultsFromApi(); | |
mCallApiButton.setEnabled(true); | |
} | |
}); | |
} | |
}); | |
} | |
/** | |
* Attempt to call the API, after verifying that all the preconditions are | |
* satisfied. The preconditions are: Google Play Services installed, an | |
* account was selected and the device currently has online access. If any | |
* of the preconditions are not satisfied, the app will prompt the user as | |
* appropriate. | |
*/ | |
private void getResultsFromApi() { | |
if (!isGooglePlayServicesAvailable()) { | |
acquireGooglePlayServices(); | |
} else if (mCredential.getSelectedAccountName() == null) { | |
chooseAccount(); | |
} else if (!isDeviceOnline()) { | |
mOutputText.setText("No network connection available."); | |
} else { | |
// new SaveTokenAsync().execute(); | |
mOutputText.setText("Credentials Initialized"); | |
initVideoPicker(); | |
} | |
} | |
private void chooseAccount() { | |
String accountName = getPreferences(Context.MODE_PRIVATE) | |
.getString(PREF_ACCOUNT_NAME, null); | |
if (accountName != null) { | |
mCredential.setSelectedAccountName(accountName); | |
// new SaveTokenAsync().execute(); | |
getResultsFromApi(); | |
} else { | |
// Start a dialog from which the user can choose an account | |
startActivityForResult( | |
mCredential.newChooseAccountIntent(), | |
REQUEST_ACCOUNT_PICKER); | |
} | |
} | |
/** | |
* Called when an activity launched here (specifically, AccountPicker | |
* and authorization) exits, giving you the requestCode you started it with, | |
* the resultCode it returned, and any additional data from it. | |
* | |
* @param requestCode code indicating which activity result is incoming. | |
* @param resultCode code indicating the result of the incoming | |
* activity result. | |
* @param data Intent (containing result data) returned by incoming | |
* activity result. | |
*/ | |
@Override | |
protected void onActivityResult( | |
int requestCode, int resultCode, Intent data) { | |
super.onActivityResult(requestCode, resultCode, data); | |
switch (requestCode) { | |
case REQUEST_GOOGLE_PLAY_SERVICES: | |
if (resultCode != RESULT_OK) { | |
mOutputText.setText( | |
"This app requires Google Play Services. Please install " + | |
"Google Play Services on your device and relaunch this app."); | |
} else { | |
getResultsFromApi(); | |
} | |
break; | |
case REQUEST_ACCOUNT_PICKER: | |
if (resultCode == RESULT_OK && data != null && | |
data.getExtras() != null) { | |
String accountName = | |
data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME); | |
if (accountName != null) { | |
mCredential.setSelectedAccountName(accountName); | |
SharedPreferences settings = | |
getPreferences(Context.MODE_PRIVATE); | |
SharedPreferences.Editor editor = settings.edit(); | |
editor.putString(PREF_ACCOUNT_NAME, accountName); | |
editor.apply(); | |
getResultsFromApi(); | |
} | |
} | |
break; | |
case REQUEST_AUTHORIZATION: | |
if (resultCode == RESULT_OK) { | |
getResultsFromApi(); | |
} | |
break; | |
case CAPTURE_RETURN: | |
case GALLERY_RETURN: | |
if (resultCode == RESULT_OK) { | |
new UploadVideoAsync(data.getData()).execute(); | |
} | |
break; | |
} | |
} | |
/* public class SaveTokenAsync extends AsyncTask<Void, Void, String> { | |
@Override | |
protected String doInBackground(Void... voids) { | |
try { | |
token = mCredential.getToken(); | |
} catch (IOException e) { | |
e.printStackTrace(); | |
} catch (GoogleAuthException e) { | |
e.printStackTrace(); | |
} | |
return token; | |
} | |
@Override | |
protected void onPostExecute(String s) { | |
super.onPostExecute(s); | |
if (s != null) { | |
SharedPreferences settings = | |
getPreferences(Context.MODE_PRIVATE); | |
SharedPreferences.Editor editor = settings.edit(); | |
editor.putString(Constants.TOKEN, token); | |
editor.apply(); | |
Constants.ACCESS_TOKEN = token; | |
} else { | |
Toast.makeText(MainActivity.this, "Token empty", Toast.LENGTH_SHORT).show(); | |
} | |
} | |
}*/ | |
/* private void initCaptureButtons() { | |
btnCaptureVideo = (Button) findViewById(R.id.btnCaptureVideo); | |
btnCaptureVideo.setOnClickListener(new View.OnClickListener() { | |
@Override | |
public void onClick(View v) { | |
Intent i = new Intent(); | |
i.setAction("android.media.action.VIDEO_CAPTURE"); | |
startActivityForResult(i, CAPTURE_RETURN); | |
} | |
}); | |
btnSelectFromGallery = (Button) findViewById(R.id.btnSelectFromGallery); | |
btnSelectFromGallery.setOnClickListener(new View.OnClickListener() { | |
@Override | |
public void onClick(View v) { | |
Intent intent = new Intent(); | |
intent.setAction(Intent.ACTION_PICK); | |
intent.setType("video/*"); | |
List<ResolveInfo> list = getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY); | |
if (list.size() <= 0) { | |
Log.d(TAG, "no video picker intent on this hardware"); | |
return; | |
} | |
startActivityForResult(intent, GALLERY_RETURN); | |
} | |
}); | |
progressBar = (ProgressBar) findViewById(R.id.progressBar); | |
progressBar.setVisibility(View.GONE); | |
btnSelectFromGallery.setEnabled(true); | |
btnCaptureVideo.setEnabled(true); | |
}*/ | |
private String uploadYoutube(Uri data) { | |
HttpTransport transport = AndroidHttp.newCompatibleTransport(); | |
// JsonFactory jsonFactory = new AndroidJsonFactory(); // GsonFactory | |
JsonFactory jsonFactory = JacksonFactory.getDefaultInstance(); | |
HttpRequestInitializer initializer = new HttpRequestInitializer() { | |
@Override | |
public void initialize(HttpRequest request) throws IOException { | |
mCredential.initialize(request); | |
request.setLoggingEnabled(true); | |
// request.setIOExceptionHandler(new HttpBackOffIOExceptionHandler(new ExponentialBackOff())); | |
} | |
}; | |
YouTube.Builder youtubeBuilder = new YouTube.Builder(transport, jsonFactory, initializer); | |
youtubeBuilder.setApplicationName(getString(R.string.app_name)); | |
// youtubeBuilder.setYouTubeRequestInitializer(new YouTubeRequestInitializer(API_KEY)); | |
YouTube youtube = youtubeBuilder.build(); | |
String PRIVACY_STATUS = "unlisted"; // or public,private | |
String PARTS = "snippet,status,contentDetails"; | |
String videoId = null; | |
try { | |
Video videoObjectDefiningMetadata = new Video(); | |
videoObjectDefiningMetadata.setStatus(new VideoStatus().setPrivacyStatus(PRIVACY_STATUS)); | |
VideoSnippet snippet = new VideoSnippet(); | |
snippet.setTitle("CALL YOUTUBE DATA API UNLISTED TEST " + System.currentTimeMillis()); | |
snippet.setDescription("MyDescription"); | |
snippet.setTags(Arrays.asList(new String[]{"TaG1,TaG2"})); | |
videoObjectDefiningMetadata.setSnippet(snippet); | |
YouTube.Videos.Insert videoInsert = youtube.videos().insert( | |
PARTS, | |
videoObjectDefiningMetadata, | |
getMediaContent(getFileFromUri(data, MainActivity.this)));/*.setOauthToken(token);*/ | |
// .setKey(API_KEY); | |
MediaHttpUploader uploader = videoInsert.getMediaHttpUploader(); | |
uploader.setDirectUploadEnabled(false); | |
MediaHttpUploaderProgressListener progressListener = new MediaHttpUploaderProgressListener() { | |
public void progressChanged(MediaHttpUploader uploader) throws IOException { | |
Log.d(TAG, "progressChanged: " + uploader.getUploadState()); | |
switch (uploader.getUploadState()) { | |
case INITIATION_STARTED: | |
break; | |
case INITIATION_COMPLETE: | |
break; | |
case MEDIA_IN_PROGRESS: | |
break; | |
case MEDIA_COMPLETE: | |
case NOT_STARTED: | |
Log.d(TAG, "progressChanged: upload_not_started"); | |
break; | |
} | |
} | |
}; | |
uploader.setProgressListener(progressListener); | |
Log.d(TAG, "Uploading.."); | |
Video returnedVideo = videoInsert.execute(); | |
Log.d(TAG, "Video upload completed"); | |
videoId = returnedVideo.getId(); | |
Log.d(TAG, String.format("videoId = [%s]", videoId)); | |
} catch (final GooglePlayServicesAvailabilityIOException availabilityException) { | |
Log.e(TAG, "GooglePlayServicesAvailabilityIOException", availabilityException); | |
} catch (UserRecoverableAuthIOException userRecoverableException) { | |
Log.i(TAG, String.format("UserRecoverableAuthIOException: %s", | |
userRecoverableException.getMessage())); | |
} catch (IOException e) { | |
Log.e(TAG, "IOException", e); | |
} | |
return videoId; | |
} | |
public class UploadVideoAsync extends AsyncTask<Void, Void, String> { | |
Uri data; | |
ProgressDialog progressDialog; | |
public UploadVideoAsync(Uri data) { | |
this.data = data; | |
} | |
@Override | |
protected void onPreExecute() { | |
super.onPreExecute(); | |
progressDialog = new ProgressDialog(MainActivity.this); | |
progressDialog.setMessage("Uploading Video to youtube"); | |
progressDialog.show(); | |
} | |
@Override | |
protected String doInBackground(Void... voids) { | |
return uploadYoutube(data); | |
} | |
@Override | |
protected void onPostExecute(String s) { | |
super.onPostExecute(s); | |
Toast.makeText(MainActivity.this, "VideoId is " + s, Toast.LENGTH_SHORT).show(); | |
Log.i("VideoId", "" + s); | |
progressDialog.dismiss(); | |
} | |
} | |
//<--------------------Utils----------------> | |
/** | |
* Checks whether the device currently has a network connection. | |
* | |
* @return true if the device has a network connection, false otherwise. | |
*/ | |
private boolean isDeviceOnline() { | |
ConnectivityManager connMgr = | |
(ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); | |
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo(); | |
return (networkInfo != null && networkInfo.isConnected()); | |
} | |
/** | |
* Check that Google Play services APK is installed and up to date. | |
* | |
* @return true if Google Play Services is available and up to | |
* date on this device; false otherwise. | |
*/ | |
private boolean isGooglePlayServicesAvailable() { | |
GoogleApiAvailability apiAvailability = | |
GoogleApiAvailability.getInstance(); | |
final int connectionStatusCode = | |
apiAvailability.isGooglePlayServicesAvailable(this); | |
return connectionStatusCode == ConnectionResult.SUCCESS; | |
} | |
/** | |
* Attempt to resolve a missing, out-of-date, invalid or disabled Google | |
* Play Services installation via a user dialog, if possible. | |
*/ | |
private void acquireGooglePlayServices() { | |
GoogleApiAvailability apiAvailability = | |
GoogleApiAvailability.getInstance(); | |
final int connectionStatusCode = | |
apiAvailability.isGooglePlayServicesAvailable(this); | |
if (apiAvailability.isUserResolvableError(connectionStatusCode)) { | |
showGooglePlayServicesAvailabilityErrorDialog(connectionStatusCode); | |
} | |
} | |
/** | |
* Display an error dialog showing that Google Play Services is missing | |
* or out of date. | |
* | |
* @param connectionStatusCode code describing the presence (or lack of) | |
* Google Play Services on this device. | |
*/ | |
void showGooglePlayServicesAvailabilityErrorDialog( | |
final int connectionStatusCode) { | |
GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance(); | |
Dialog dialog = apiAvailability.getErrorDialog( | |
MainActivity.this, | |
connectionStatusCode, | |
REQUEST_GOOGLE_PLAY_SERVICES); | |
dialog.show(); | |
} | |
private static File getFileFromUri(Uri uri, Activity activity) { | |
try { | |
String filePath = null; | |
String[] proj = {MediaStore.Video.VideoColumns.DATA}; | |
Cursor cursor = activity.getContentResolver().query(uri, proj, null, null, null); | |
if (cursor.moveToFirst()) { | |
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Video.VideoColumns.DATA); | |
filePath = cursor.getString(column_index); | |
} | |
cursor.close(); | |
File file = new File(filePath); | |
cursor.close(); | |
return file; | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
return null; | |
} | |
private AbstractInputStreamContent getMediaContent(File file) throws FileNotFoundException { | |
InputStreamContent mediaContent = new InputStreamContent( | |
"video/*", | |
new BufferedInputStream(new FileInputStream(file))); | |
mediaContent.setLength(file.length()); | |
return mediaContent; | |
} | |
private void initVideoPicker() { | |
Intent intent = new Intent(); | |
intent.setAction(Intent.ACTION_PICK); | |
intent.setType("video/*"); | |
List<ResolveInfo> list = getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY); | |
if (list.size() <= 0) { | |
Log.d(TAG, "no video picker intent on this hardware"); | |
Toast.makeText(MainActivity.this, "No video picker found on device", Toast.LENGTH_SHORT).show(); | |
return; | |
} | |
startActivityForResult(intent, GALLERY_RETURN); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment