2013-08-02 7 views
5

Ich arbeite an einer Android-App, die Videos aufzeichnet und es dem Nutzer ermöglicht, sie mithilfe des YouTube Data API v3 direkt auf YouTube hochzuladen.YouTube API 3 Video hochladen - Zugriff nicht konfiguriert - Android

Ich habe meine App in Google API-Konsole eingerichtet. Unter Dienste habe ich YouTube Data API v3 aktiviert. Unter API-Zugang habe ich sowohl einen Abschnitt "Client ID für installierte Anwendungen" (einschließlich einer Client ID und Client Secret) und einen Abschnitt "Simple API Access" -> "Schlüssel für Android Apps (mit Zertifikaten)" (welcher einen API Schlüssel enthält) und einen "Android Apps" Abschnitt, der vorerst leer bleibt, dh alle Android Apps zulassen, aber ich habe es mit der Einstellung meines Android-Schlüssels versucht).

Ich habe meinen Code aus einer Reihe von Orten basiert in erster Linie:

https://developers.google.com/youtube/v3/code_samples/java#upload_a_video

und

https://code.google.com/p/google-api-java-client/source/browse/tasks-android-sample/src/main/java/com/google/api/services/samples/tasks/android/TasksSample.java?repo=samples

Der Upload OK initialisiert, beginnt die AsyncTask, aber dann bekomme ich eine IOException geworfen sagen:

{ 
    "code": 403, 
    "errors": [ 
     { 
      "domain": "usageLimits", 
      "message": "Access Not Configured", 
      "reason": "accessNotConfigured" 
     } 
    ], 
    "message": "Access Not Configured" 
} 

Ähnliche SO-Beiträge deuten darauf hin, dass es mit meinen Google-API-Konsoleneinstellungen zu tun hat, aber ich kann nichts falsch finden. Irgendwelche Vorschläge? Ich frage mich, ob es daran liegt, dass ich meine Kundennummer oder mein Geheimnis nirgendwo hingebe ...

Danke.

Mein Code läuft von einem Fragment mit einer Liste von Videos. Die entsprechenden Abschnitte sind:

- Init

public class UploadFragment 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; 

- Setup-Anmeldeinformationen und youtube

@Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
      Bundle savedInstanceState) { 
     ... 
     credential = googleAccountCredential(scopes); 
     youtube = new YouTube.Builder(transport, jsonFactory, credential) 
      .setApplicationName("MyAppName") 
      .build(); 
     ... 
    } 

- Auf Schaltfläche klicken, starten Sie laden

@Override void onClick(View v) { 
     ... 
     if (hasGooglePlayServices()) { 
      uploadYouTubeVideos(); 

     ... 
    } 

- Bauen Berechtigungsnachweis

/** 
    * Get the credential to authorize the installed application to access user's protected data. 
    * 
    * @param scopes list of scopes needed to run YouTube upload. 
    */ 
    private static GoogleAccountCredential googleAccountCredential(List<String> scopes) throws Exception { 
     credential = GoogleAccountCredential.usingOAuth2(context, scopes) 
      .setSelectedAccountName(PreferenceManager.getAccountName()); 
     return credential; 
    } 

- ein Konto aus den

Benutzern anfordern
/** 
    * Fire intent to get user to choose account 
    * Return to onActivityResult 
    */ 
    private void chooseAccount() { 
     startActivityForResult(credential.newChooseAccountIntent(), REQUEST_ACCOUNT_PICKER); 
    } 

- Bei der Rückkehr von dem Benutzer der Wahl und Konto -/anfordernden Genehmigung

/** 
    * Returns from chooseAccount and from request authorization 
    */ 
    @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; 
     } 
    } 

- Called mehrmals je nachdem, was Informationen, die wir haben - Konto, Autorisierung usw.

/** 
    * Uploads user selected video to the user's YouTube account using OAuth2 
    * for authentication. 
    * 
    * @param videoFile file to be uploaded 
    */ 
    public void uploadYouTubeVideos() { 
     if (credential.getSelectedAccountName() == null) { 
      chooseAccount(); 
     } else { 
      File videoFile = getVideoFile(); 
      Insert videoInsert = prepareUpload(videoFile); 
      new VideoUploadAsyncTask().execute(videoInsert); 
     } 
    } 

- Bereiten Sie den Upload - bringt alles zusammen

/** 
    * Prepare upload. Just leaves execute to be run in AsyncTask. 
    * 
    * @param videoFile file to be uploaded 
    * @return 
    */ 
    public 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; 
     } 
    } 

- Erfordern Google-Dienste spielen

/** 
    * Pop up dialog requesting user to download Google Play Services. 
    * Returns to onActivityResult 
    */ 
    void showGooglePlayServicesAvailabilityErrorDialog(final int connectionStatusCode) { 
     getActivity().runOnUiThread(new Runnable() { 
      public void run() { 
       Dialog dialog = 
         GooglePlayServicesUtil.getErrorDialog(connectionStatusCode, getActivity(), 
         REQUEST_GOOGLE_PLAY_SERVICES); 
       dialog.show(); 
      } 
     }); 
    } 

- AsyncTask die

auf dem Upload läuft ausführen
public class VideoUploadAsyncTask extends AsyncTask<Insert, Void, Void> { 
     @Override 
     protected Void doInBackground(Insert... inserts) { 
      Insert videoInsert = inserts[0]; 
      try { 
       Video returnVideo = videoInsert.execute(); 
      } catch (final GooglePlayServicesAvailabilityIOException availabilityException) { 
       showGooglePlayServicesAvailabilityErrorDialog(
         availabilityException.getConnectionStatusCode()); 
      } catch (UserRecoverableAuthIOException userRecoverableException) { 
       startActivityForResult(
         userRecoverableException.getIntent(), UploadFragment.REQUEST_AUTHORIZATION); 
      } catch (IOException e) { 
       Log.e(TAG, "IOException: " + e.getMessage()); 
      } 
      return null; 
     } 
    } 

} 
+0

Die verwandten Fragen von SO wies mich auf https://github.com/youtube/ytd-android, ich werde einen genaueren Blick darauf haben, aber auf den ersten Blick scheint es, dass wir eine sehr ähnliche Methode verwenden . –

+0

Hallo, können Sie den ganzen Code als Referenz posten? –

+0

Ich bin verwirrt mit dem "Android API Key" auf der Projekthomepage geschrieben. Heißt das "Client ID für Android-Anwendung"? –

Antwort

3

Die Antwort von @Ibrahim war fast richtig für mich. Was ich tun musste, war meine API-Konfiguration zu bearbeiten. Es war jedoch nicht der Abschnitt "Einfacher API-Zugriff", den ich bearbeiten musste, sondern die Einstellungen nach dem Klicken auf die Schaltfläche "Eine andere Client-ID erstellen".

Dann könnte ich "Installierte Anwendung" -> "Android" wählen. Nachdem ich meinen Paketnamen und SHA1 eingegeben und 15 Minuten gewartet hatte, funktionierte meine App wie erwartet. Ich habe auch den "Simple API access" eingerichtet. Ich bin mir nicht sicher, ob du beides brauchst oder nicht.

+0

Hallo Jon G, ich habe nicht verstanden, kannst du bitte klar erklären, was du getan hast. weil ich die gleichen Probleme bezüglich der Authentifizierung in meiner App habe. Danke im Voraus – siva

2

Ja, YouTube Direct Lite für Android ist ähnlich. Sie müssen den einfachen API-Zugriff mit Ihrem SHA1-Schlüssel konfigurieren. Explains here.

+0

Danke für Ihre Antwort @Ibrahim. Ich habe es versucht und es jetzt nochmal überprüft ... es scheint keinen Unterschied zu machen. Ich habe einen SHA1-Schlüssel erstellt und dieser zu meiner API-Konsole hinzugefügt: Schlüssel; com.bla.bla.myapp –

+0

Wenn Sie die Konsole aktualisieren, geben Sie 15 Minuten oder so. –

+0

Immer noch kein Glück @Ibrahim. Ich stelle fest, dass ich nirgends in meinem Code meinen API-Schlüssel verwende ... In einem früheren Versuch habe ich einen "YouTubeRequestInitializer" anstelle eines "GoogleAccountCredential" verwendet, um mein YouTube-Objekt zu initialisieren, das den API-Schlüssel als Eingabe verwendet. Soll ich den API-Schlüssel irgendwo in GoogleAccountCredential angeben? –

Verwandte Themen