1

I followed Google's Java Quickstart guide to try to develop a search function for Google Drive files. After I executed gradle -q run or gradle run command, it open a web page and shows "Error: redirect_uri_mismatch" message.

The errors messages:

Here is the code:

package main.java;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.List;

import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.client.util.store.FileDataStoreFactory;
import com.google.api.services.drive.Drive;
import com.google.api.services.drive.DriveScopes;
import com.google.api.services.drive.model.File;
import com.google.api.services.drive.model.FileList;

public class Quickstart {
    /** Application name. */
    private static final String APPLICATION_NAME = "Drive API Java Quickstart";

    /** Directory to store user credentials for this application. */
    private static final java.io.File DATA_STORE_DIR = new java.io.File(System.getProperty("user.home"),
            ".credentials/drive-java-quickstart");

    /** Global instance of the {@link FileDataStoreFactory}. */
    private static FileDataStoreFactory DATA_STORE_FACTORY;

    /** Global instance of the JSON factory. */
    private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();

    /** Global instance of the HTTP transport. */
    private static HttpTransport HTTP_TRANSPORT;

    /**
     * Global instance of the scopes required by this quickstart.
     *
     * If modifying these scopes, delete your previously saved credentials at
     * ~/.credentials/drive-java-quickstart
     */
    private static final List<String> SCOPES = Arrays.asList(DriveScopes.DRIVE_METADATA_READONLY);

    static {
        try {
            HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
            DATA_STORE_FACTORY = new FileDataStoreFactory(DATA_STORE_DIR);
        } catch (Throwable t) {
            t.printStackTrace();
            System.exit(1);
        }
    }

    /**
     * Creates an authorized Credential object.
     * 
     * @return an authorized Credential object.
     * @throws IOException
     */
    public static Credential authorize() throws IOException {
        // Load client secrets.
        InputStream in = Quickstart.class.getResourceAsStream("/client_secret.json");
        GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in));

        // Build flow and trigger user authorization request.
        GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(HTTP_TRANSPORT, JSON_FACTORY,
                clientSecrets, SCOPES).setDataStoreFactory(DATA_STORE_FACTORY).setAccessType("offline").build();
        Credential credential = new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user");
        System.out.println("Credentials saved to " + DATA_STORE_DIR.getAbsolutePath());
        return credential;
    }

    /**
     * Build and return an authorized Drive client service.
     * 
     * @return an authorized Drive client service
     * @throws IOException
     */
    public static Drive getDriveService() throws IOException {
        Credential credential = authorize();
        return new Drive.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential).setApplicationName(APPLICATION_NAME).build();
    }

    public static void main(String[] args) throws IOException {
        // Build a new authorized API client service.
        Drive service = getDriveService();

        // Print the names and IDs for up to 10 files.
        FileList result = service.files().list().setPageSize(10).setFields("nextPageToken, files(id, name)").execute();
        List<File> files = result.getFiles();
        if (files == null || files.size() == 0) {
            System.out.println("No files found.");
        } else {
            System.out.println("Files:");
            for (File file : files) {
                System.out.printf("%s (%s)\n", file.getName(), file.getId());
            }
        }
    }
}

The development environment:

The build.gradle file:

apply plugin: 'java'
apply plugin: 'application'

mainClassName = 'Quickstart'
sourceCompatibility = 1.7
targetCompatibility = 1.7
version = '1.0'

repositories {
    mavenCentral()
}

dependencies {
    compile 'com.google.api-client:google-api-client:1.22.0'
    compile 'com.google.oauth-client:google-oauth-client-jetty:1.22.0'
    compile 'com.google.apis:google-api-services-drive:v3-rev68-1.22.0' 
}

My Google Developer Console:

What should I do to successfully run the gradle -q run or gradle run command? How to correctly configure the "Redirect_URI"?

Jack
  • 347
  • 1
  • 2
  • 22

1 Answers1

1

Based from this thread, if you are using the Gradle Wrapper (the recommended option in Android Studio), you enable stacktrace by running gradlew compileDebug --stacktrace from the command line in the root folder of your project (where the gradlew file is). If you are not using the gradle wrapper, you use gradle compileDebug --stacktrace instead (presumably). With this, you can know the root of your error.

You don't really need to run with --stacktrace though, running gradlew compileDebug by itself, from the command line, should tell you where the error is.

You may also try cleaning your project by going to the following menu item: Project > Clean... If that doesn't work, try removing the jars from the build path and add them again.

Additional:

How to correctly configure the "Redirect_URI"?

You may check this SO thread: How to set redirect_uri in google developer console?.

The redirect URI is an object only used by web applications that are doing oAuth2 authentication; so, when you create a new client ID, choose "web application" as the ID type and there will be a text area where you enter all of the allowed redirect URIs (these web pages will be coded by you, and will need to perform the function of doing the oauth2 ticket verification).

If your app is not a web application, you choose "installed application" as the type and you'll get a key that can be used in an Android/iOS/desktop app. However, this key will NOT be useable, at all, in a web application.

If your web application doesn't need to write any data or upload any files, you can create a public API key that you just include as a parameter with your requests.

Service accounts (which you're showing in the image above) are not compatible with the YouTube API.

Community
  • 1
  • 1
abielita
  • 13,147
  • 2
  • 17
  • 59
  • Hi @abielita, I have a progress and update the question. PTAL. Do you know how to configure the "redirect_URI"? – Jack Apr 11 '17 at 08:40
  • 2
    Thanks for @abielita. I found the solution!! I should choose the "Application type" to "Other" not "Web application". – Jack Apr 11 '17 at 09:12
  • 1
    @Jack thanks your comment was helpful. I was getting the same error and after changing application type to "other" it solved the problem. But I found literally nothing where this is mentioned. Thanks btw!:) – AmitB10 Jan 04 '18 at 15:31