我正在将视频上传到 youtube,默认情况下会上传给已登录 google 帐户的用户。
但我想设置所有视频都应该使用我的静态 gmailID 和密码上传
是否可以使用静态电子邮件 ID 和密码直接登录谷歌帐户?
或任何其他好的 api 或示例在 youtube 中上传视频。
提前致谢....
我正在将视频上传到 youtube,默认情况下会上传给已登录 google 帐户的用户。
但我想设置所有视频都应该使用我的静态 gmailID 和密码上传
是否可以使用静态电子邮件 ID 和密码直接登录谷歌帐户?
或任何其他好的 api 或示例在 youtube 中上传视频。
提前致谢....
我已将MAC 的答案中提到的项目的上传功能包装到单个实用程序类中:
这是YoutubeUploader.java
import java.io.BufferedReader;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Set;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.database.Cursor;
import android.net.Uri;
import android.provider.MediaStore.Video;
import android.util.Log;
public class YoutubeUploader {
private static final String TAG = "YoutubeUploader";
// After creating project at http://www.appspot.com DEFAULT_YTD_DOMAIN == <Developers Console Project ID>.appspot.com [ You can find from Project -> Administration -> Application settings]
public static final String DEFAULT_YTD_DOMAIN = "developerconsolid.appspot.com";
// I used Google APIs Console Project Title as Domain name:
public static final String DEFAULT_YTD_DOMAIN_NAME = "Domain Name";
//From Google Developer Console from same project (Created by SHA1; project package)
//Example https://console.developers.google.com/project/apps~gtl-android-youtube-test/apiui/credential
public static final String DEVELOPER_KEY = "developer key";
// CLIENT_ID == Google APIs Console Project Number:
public static final String CLIENT_ID = "client_id";
public static final String YOUTUBE_AUTH_TOKEN_TYPE = "youtube";
private static final String AUTH_URL = "https://www.google.com/accounts/ClientLogin";
// Uploader's user-name and password
private static final String USER_NAME = "usersemail@useremail.usersemail";
private static final String PASSWORD = "userspassword";
private static final String INITIAL_UPLOAD_URL = "https://uploads.gdata.youtube.com/resumable/feeds/api/users/default/uploads";
private static String getClientAuthToken() {
try {
URL url = new URL(AUTH_URL);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("POST");
urlConnection.setDoOutput(true);
urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
String template = "Email=%s&Passwd=%s&service=%s&source=%s";
String userName = USER_NAME; // TODO
String password = PASSWORD; // TODO
String service = YOUTUBE_AUTH_TOKEN_TYPE;
String source = CLIENT_ID;
userName = URLEncoder.encode(userName, "UTF-8");
password = URLEncoder.encode(password, "UTF-8");
String loginData = String.format(template, userName, password, service, source);
OutputStreamWriter outStreamWriter = new OutputStreamWriter(urlConnection.getOutputStream());
outStreamWriter.write(loginData);
outStreamWriter.close();
int responseCode = urlConnection.getResponseCode();
if (responseCode != 200) {
Log.d(TAG, "Got an error response : " + responseCode + " " + urlConnection.getResponseMessage());
throw new IOException(urlConnection.getResponseMessage());
} else {
InputStream is = urlConnection.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line = null;
while ((line = br.readLine()) != null) {
if (line.startsWith("Auth=")) {
String split[] = line.split("=");
String token = split[1];
Log.d(TAG, "Auth Token : " + token);
return token;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static String upload(YoutubeUploadRequest uploadRequest, ProgressListner listner, Activity activity) {
totalBytesUploaded = 0;
String authToken = getClientAuthToken();
if(authToken != null) {
String uploadUrl = uploadMetaData(uploadRequest, authToken, activity, true);
File file = getFileFromUri(uploadRequest.getUri(), activity);
long currentFileSize = file.length();
int uploadChunk = 1024 * 1024 * 3; // 3MB
int start = 0;
int end = -1;
String videoId = null;
double fileSize = 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, authToken, listner);
fileSize -= uploadChunk;
start = end + 1;
} catch (IOException e) {
Log.d(TAG,"Error during upload : " + e.getMessage());
}
}
if (videoId != null) {
return videoId;
}
}
return null;
}
public static int totalBytesUploaded = 0;
@SuppressLint("DefaultLocale")
@SuppressWarnings("resource")
private static String gdataUpload(File file, String uploadUrl, int start, int end, String clientLoginToken, ProgressListner listner) throws IOException {
int chunk = end - start + 1;
int bufferSize = 4096;
byte[] buffer = new byte[bufferSize];
FileInputStream fileStream = new FileInputStream(file);
URL url = new URL(uploadUrl);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestProperty("Authorization", String.format("GoogleLogin auth=\"%s\"", clientLoginToken));
urlConnection.setRequestProperty("GData-Version", "2");
urlConnection.setRequestProperty("X-GData-Client", CLIENT_ID);
urlConnection.setRequestProperty("X-GData-Key", String.format("key=%s", DEVELOPER_KEY));
// some mobile proxies do not support PUT, using X-HTTP-Method-Override to get around this problem
urlConnection.setRequestMethod("POST");
urlConnection.setRequestProperty("X-HTTP-Method-Override", "PUT");
urlConnection.setDoOutput(true);
urlConnection.setFixedLengthStreamingMode(chunk);
urlConnection.setRequestProperty("Content-Type", "video/3gpp");
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);
double currentFileSize = file.length();
int bytesRead;
int totalRead = 0;
while ((bytesRead = fileStream.read(buffer, 0, bufferSize)) != -1) {
outStreamWriter.write(buffer, 0, bytesRead);
totalRead += bytesRead;
totalBytesUploaded += bytesRead;
double percent = (totalBytesUploaded / currentFileSize) * 100;
if(listner != null){
listner.onUploadProgressUpdate((int) percent);
}
System.out.println("GTL You tube upload progress: " + percent + "%");
/*
Log.d(LOG_TAG, String.format(
"fileSize=%f totalBytesUploaded=%f percent=%f", currentFileSize,
totalBytesUploaded, percent));
*/
//dialog.setProgress((int) percent);
// TODO My settings
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());
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 succesfully
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;
}
private static 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();
if (nodeName != null && nodeName.equals("yt:videoid")) {
return node.getFirstChild().getNodeValue();
}
}
return null;
}
private static File getFileFromUri(Uri uri, Activity activity) {
try {
String filePath = null;
String[] proj = { Video.VideoColumns.DATA };
Cursor cursor = activity.getContentResolver().query(uri, proj, null, null, null);
if(cursor.moveToFirst()) {
int column_index = cursor.getColumnIndexOrThrow(Video.VideoColumns.DATA);
filePath = cursor.getString(column_index);
}
cursor.close();
//String filePath = cursor.getString(cursor.getColumnIndex(Video.VideoColumns.DATA));
File file = new File(filePath);
cursor.close();
return file;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static String uploadMetaData(YoutubeUploadRequest uploadRequest, String clientLoginToken, Activity activity, boolean retry) {
try {
File file = getFileFromUri(uploadRequest.getUri(), activity);
if(file != null) {
String uploadUrl = INITIAL_UPLOAD_URL;
URL url = new URL(uploadUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestProperty("Authorization", String.format("GoogleLogin auth=\"%s\"", clientLoginToken));
connection.setRequestProperty("GData-Version", "2");
connection.setRequestProperty("X-GData-Client", CLIENT_ID);
connection.setRequestProperty("X-GData-Key", String.format("key=%s", DEVELOPER_KEY));
connection.setRequestMethod("POST");
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "application/atom+xml");
connection.setRequestProperty("Slug", file.getAbsolutePath());
String title = uploadRequest.getTitle();
String description = uploadRequest.getDescription();
String category = uploadRequest.getCategory();
String tags = uploadRequest.getTags();
String template = readFile(activity, R.raw.gdata).toString();
String atomData = String.format(template, title, description, category, tags);
/*String template = readFile(activity, R.raw.gdata_geo).toString();
atomData = String.format(template, title, description, category, tags,
videoLocation.getLatitude(), videoLocation.getLongitude());*/
OutputStreamWriter outStreamWriter = new OutputStreamWriter(connection.getOutputStream());
outStreamWriter.write(atomData);
outStreamWriter.close();
int responseCode = connection.getResponseCode();
if (responseCode < 200 || responseCode >= 300) {
// The response code is 40X
if ((responseCode + "").startsWith("4") && retry) {
Log.d(TAG, "retrying to fetch auth token for ");
clientLoginToken = getClientAuthToken();
// Try again with fresh token
return uploadMetaData(uploadRequest, clientLoginToken, activity, false);
} else {
return null;
}
}
return connection.getHeaderField("Location");
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
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
}
}
}
public static interface ProgressListner {
void onUploadProgressUpdate(int progress);
}
}
这是YoutubeUploadRequest.java
import android.net.Uri;
public class YoutubeUploadRequest {
private static final String DEFAULT_VIDEO_CATEGORY = "News";
private static final String DEFAULT_VIDEO_TAGS = "mobile";
private String title;
private String strUri;
private String description;
private String category = DEFAULT_VIDEO_CATEGORY;
private String tags = DEFAULT_VIDEO_TAGS;
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
public String getTags() {
return tags;
}
public void setTags(String tags) {
this.tags = tags;
}
public String getStrUri() {
return strUri;
}
public void setStrUri(String strUri) {
this.strUri = strUri;
}
public Uri getUri() {
return Uri.parse(strUri);
}
public void setUri(Uri uri) {
this.strUri = uri.toString();
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
你也需要raw/gdata.xml
<?xml version="1.0"?> <entry xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" xmlns:yt="http://gdata.youtube.com/schemas/2007"> <media:group> <media:title type="plain">%s</media:title> <media:description type="plain">%s</media:description> <media:category scheme="http://gdata.youtube.com/schemas/2007/categories.cat">%s</media:category> <media:keywords>%s</media:keywords> </media:group> </entry>
这是使用它的示例活动:MainActivity.java
import java.util.List;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.Toast;
import com.example.trialanderror.YoutubeUploader.ProgressListner;
public class MainActivity extends Activity {
private static final String TAG = "MainActivity";
private static final int CAPTURE_RETURN = 1;
private static final int GALLERY_RETURN = 2;
private static final int SUBMIT_RETURN = 3;
private ProgressBar progressBar;
private Button btnCaptureVideo;
private Button btnSelectFromGallery;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnCaptureVideo = (Button) findViewById(R.id.btnCaptureVideo);
btnCaptureVideo.setOnClickListener(new 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 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);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case CAPTURE_RETURN:
case GALLERY_RETURN:
if (resultCode == RESULT_OK) {
/*Intent intent = new Intent(this, SubmitActivity.class);
intent.setData(data.getData());
startActivityForResult(intent, SUBMIT_RETURN);*/
progressBar.setVisibility(View.VISIBLE);
btnSelectFromGallery.setEnabled(false);
btnCaptureVideo.setEnabled(false);
uploadYoutube(data.getData());
}
break;
case SUBMIT_RETURN:
if (resultCode == RESULT_OK) {
Toast.makeText(MainActivity.this, "thank you!", Toast.LENGTH_LONG).show();
} else {
// Toast.makeText(DetailsActivity.this, "submit failed or cancelled",
// Toast.LENGTH_LONG).show();
}
break;
}
}
private void uploadYoutube(final Uri data) {
new AsyncTask<Void, Integer, Void>() {
@Override
protected Void doInBackground(Void... params) {
YoutubeUploadRequest request = new YoutubeUploadRequest();
request.setUri(data);
//request.setCategory(category);
//request.setTags(tags);
request.setTitle("MPRJ Video Tite");
request.setDescription("MPRJ Video Test");
YoutubeUploader.upload(request, new ProgressListner() {
@Override
public void onUploadProgressUpdate(int progress) {
publishProgress(progress);
}
}, MainActivity.this);
return null;
}
@Override
protected void onProgressUpdate(Integer... values) {
progressBar.setProgress(values[0]);
if(values[0] == 100){
progressBar.setVisibility(View.GONE);
btnSelectFromGallery.setEnabled(true);
btnCaptureVideo.setEnabled(true);
}
};
}.execute();
}
}
示例活动的布局activity_main.xml
<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"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="20dp"
android:text="@string/upload_video" />
<Button
android:id="@+id/btnCaptureVideo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/capture_video" />
<Button
android:id="@+id/btnSelectFromGallery"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:text="@string/select_from_gallery" />
<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_marginTop="15dp"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
我已成功上传 youtube 视频。
通过使用这个
脚步:
1) 从此链接下载 ytd-android-0.2.tar.gz
2) 导入为 android 项目。
3) 将文件:GlsAuthorizer.java替换为ClientLoginAuthorizer.java
4)在ClientLoginAuthorizer.java中设置用户名和密码
5) 在www.appspot.com注册您的电子邮件 ID
6) 在string.xml 文件中设置所有值
7)运行项目.....给你。
ClientLoginAuthorizer.java的代码
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import android.app.Activity;
import android.content.Context;
import android.util.Log;
/**
* Created by IntelliJ IDEA. User: jarekw Date: Nov 18, 2010 Time: 11:21:36 PM
* To change this template use File | Settings | File Templates.
*/
public class ClientLoginAuthorizer implements Authorizer {
public static final String YOUTUBE_AUTH_TOKEN_TYPE = "youtube";
private static final String AUTH_URL = "https://www.google.com/accounts/ClientLogin";
private Context ctx;
private static final String LOG_TAG = ClientLoginAuthorizer.class
.getSimpleName();
public ClientLoginAuthorizer(Context context) {
this.ctx = context;
}
@Override
public void fetchAccounts(AuthorizationListener<String[]> listener) {
// not used
}
@Override
public void addAccount(Activity activity,
AuthorizationListener<String> listener) {
// not used
}
@Override
public void fetchAuthToken(String accountName, Activity activity,
AuthorizationListener<String> listener) {
Log.d(LOG_TAG, "Getting " + YOUTUBE_AUTH_TOKEN_TYPE + " authToken for "
+ accountName);
try {
String token = getCLAuthToken(accountName);
listener.onSuccess(token);
} catch (Exception e) {
listener.onError(e);
}
}
@Override
public String getAuthToken(String accountName) {
try {
String token = getCLAuthToken(accountName);
return token;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
public String getCLAuthToken(String accountName) throws IOException {
HttpURLConnection urlConnection = getGDataUrlConnection(AUTH_URL);
urlConnection.setRequestMethod("POST");
urlConnection.setDoOutput(true);
urlConnection.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");
String template = "Email=%s&Passwd=%s&service=%s&source=%s";
String userName = "USERNAME"; // TODO
String password = "PASSWORD"; // TODO
String service = YOUTUBE_AUTH_TOKEN_TYPE;
String source = ctx.getString(R.string.client_id);
String loginData = String.format(template, encode(userName),
encode(password), service, source);
OutputStreamWriter outStreamWriter = new OutputStreamWriter(
urlConnection.getOutputStream());
outStreamWriter.write(loginData);
outStreamWriter.close();
int responseCode = urlConnection.getResponseCode();
if (responseCode != 200) {
Log.d(LOG_TAG, "Got an error response : " + responseCode + " "
+ urlConnection.getResponseMessage());
throw new IOException(urlConnection.getResponseMessage());
} else {
InputStream is = urlConnection.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line = null;
while ((line = br.readLine()) != null) {
if (line.startsWith("Auth=")) {
String split[] = line.split("=");
String token = split[1];
Log.d(LOG_TAG, "Auth Token : " + token);
return token;
}
}
}
throw new IOException("Could not read response");
}
private String encode(String string) throws UnsupportedEncodingException {
return URLEncoder.encode(string, "UTF-8");
}
private HttpURLConnection getGDataUrlConnection(String urlString)
throws IOException {
URL url = new URL(urlString);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
return connection;
}
@Override
public String getFreshAuthToken(String accountName, String authToken) {
return getAuthToken(accountName);
}
public static class ClientLoginAuthorizerFactory implements
AuthorizerFactory {
public Authorizer getAuthorizer(Context context, String authTokenType) {
return new ClientLoginAuthorizer(context);
}
}
}