2013-08-02 15 views
5

Sto lavorando a un'app Android che registra video e consente all'utente di caricarlo direttamente su YouTube utilizzando l'API dei dati di YouTube v3.YouTube API 3 Carica video - Accesso non configurato - Android

Ho impostato la mia app nella console API di Google. Sotto i servizi, ho abilitato l'API di dati di YouTube v3. Sotto accesso API ho sia una sezione "ID client per applicazioni installate" (incluso un Client ID e Client Secret) e una sezione "Accesso API semplice" -> "Chiave per app Android (con certificati)" (che include una chiave API e una sezione "App Android", che per ora è vuota, ovvero consente tutte le app Android, ma l'ho provata impostando la mia chiave Android).

Ho basato il mio codice da un certo numero di posti, in primo luogo:

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

e

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

Il caricamento inizializza OK, inizia l'AsyncTask, ma poi ho un Detto IOException:

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

Simili post di SO suggeriscono che abbia a che fare con le mie impostazioni della console dell'API di Google, ma non riesco a trovare nulla di sbagliato. Eventuali suggerimenti? Mi chiedo se è perché non sto fornendo il mio ID cliente o segreto da nessuna parte ...

Grazie.

Il mio codice viene eseguito da un frammento contenente un elenco di video. Le sezioni pertinenti sono:

- 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; 

- Impostazione di credenziali e youtube

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

- Su clic del pulsante, avviare caricare

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

     ... 
    } 

- Costruire credenziali

/** 
    * 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; 
    } 

- richiedere un account da parte dell'utente

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

- Al ritorno da parte dell'utente di scegliere e rappresentano -/che richiedono l'autorizzazione

/** 
    * 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; 
     } 
    } 

- chiamato più volte a seconda di ciò informazioni abbiamo - account, autorizzazione, ecc.

/** 
    * 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); 
     } 
    } 

- Preparare il caricamento - mette tutto insieme

/** 
    * 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; 
     } 
    } 

- richiedono Google Play Services

/** 
    * 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 che corre eseguire sul caricamento

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

Le domande correlate fornite da SO mi hanno indirizzato a https://github.com/youtube/ytd-android, avrò un aspetto più dettagliato, ma a prima vista, sembra che stiamo usando un metodo molto simile . –

+0

Ciao, puoi pubblicare l'intero codice per riferimento? –

+0

Sono confuso con la "Chiave API Android" scritta nella home page del progetto. Significa "ID client per l'applicazione Android"? –

risposta

3

La risposta fornita da @Ibrahim era quasi corretta per me. Quello che dovevo fare era modificare la mia configurazione API. Tuttavia, non era la sezione "Accesso API semplice" che avevo bisogno di modificare, erano le impostazioni dopo aver fatto clic sul pulsante "Crea un altro ID cliente".

Quindi ho potuto selezionare "Applicazione installata" -> "Android". Dopo aver inserito il nome del pacchetto e SHA1, e in attesa di 15 minuti, la mia app ha funzionato come previsto. Ho anche impostato l'accesso "Accesso API semplice". Non sono sicuro che tu abbia bisogno di entrambi o meno.

+0

Ciao Jon G, non ho capito, per favore, puoi spiegare chiaramente quello che hai fatto. perché ho gli stessi problemi relativi all'aquisizione nella mia app. Grazie in anticipo – siva

2

Sì, YouTube Direct Lite per Android è simile. Devi configurare un semplice accesso API con la tua chiave SHA1. Explains here.

+0

Grazie per la tua risposta @Ibrahim. Ho dato una prova, e ricontrollato ora ... non sembra fare la differenza. Ho creato una chiave SHA1 e l'ho aggiunta alla console API come: chiave ; com.bla.bla.myapp –

+0

Quando si aggiorna la console, somministrarla per circa 15 minuti. –

+0

Ancora senza fortuna @Ibrahim. Ho notato che da nessuna parte nel mio codice uso la mia chiave API ... In un precedente tentativo ho utilizzato un "YouTubeRequestInitializer" invece di un "GoogleAccountCredential" per inizializzare il mio oggetto YouTube, che accetta la chiave API come input. Dovrei includere la chiave API da qualche parte in GoogleAccountCredential? –