目录

Drive Kit手工转换指导书

开发准备

您若需要应用支持Drive Kit,必须完成接入准备,请参见开发准备。

登录方式变更

HMS使用华为帐号进行登录,并以此获取鉴权信息、证书等。获取HMS Credential的过程与Google API相差较大,需要手动转换。

下面提供了HMS登录阶段获取unionId、accessToken来生成Credential的示例代码,您可以参考代码进行修改。

Google API:

public class DriveQuickstart {
    private static final String APPLICATION_NAME = "Google Drive API Java Quickstart";
    private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
    private static final String TOKENS_DIRECTORY_PATH = "tokens";
    /**     
      * Global instance of the scopes required by this quickstart.     
      * If modifying these scopes, delete your previously saved tokens/ folder.    
      */
    private static final List<String> SCOPES = Collections.singletonList(DriveScopes.DRIVE_METADATA_READONLY);
    private static final String CREDENTIALS_FILE_PATH = "/credentials.json";
    /**     
      * Creates an authorized Credential object.     
      * @param HTTP_TRANSPORT The network HTTP Transport.     
      * @return An authorized Credential object.     
      * @throws IOException If the credentials.json file cannot be found.     
      */
    private static Credential getCredentials(final NetHttpTransport HTTP_TRANSPORT) throws IOException {
        // Load client secrets.
        InputStream in = DriveQuickstart.class.getResourceAsStream(CREDENTIALS_FILE_PATH);
        if (in == null) {
            throw new FileNotFoundException("Resource not found: " + CREDENTIALS_FILE_PATH);
        }
        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(new FileDataStoreFactory(new java.io.File(TOKENS_DIRECTORY_PATH)))
            .setAccessType("offline")
            .build();
        LocalServerReceiver receiver = new LocalServerReceiver.Builder().setPort(8888).build();
        return new AuthorizationCodeInstalledApp(flow, receiver).authorize("user");
    }
}

HMS API示例代码:

public class LoginActivity extends Activity implements View.OnClickListener {
    private static DriveCredential.AccessMethod refreshAT = new DriveCredential.AccessMethod() {
        @Override
        public String refreshToken() {
            return HmsProxyImpl.getInstance().refreshAccessToken();
        }
    };
	@Override
    public void onClick(View v) {
        if (R.id.account_login_button == v.getId()) {
            HmsProxyImpl.getInstance().signIn(this);
        }
    }
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch (requestCode) {
            case HmsProxyImpl.REQUEST_SIGN_IN_LOGIN:
                com.huawei.hmf.tasks.Task<AuthHuaweiId> signInHuaweiIdTask = HuaweiIdAuthManager.parseAuthResultFromIntent(data);
                if (signInHuaweiIdTask.isSuccessful()) {
                    AuthHuaweiId huaweiAccount = signInHuaweiIdTask.getResult();
                    HmsProxyImpl.getInstance().dealSignInResult(huaweiAccount);
                    initDrive();
                } else {
                    finish();
                }
                break;
            default:
                break;
        }
    }
    private void initDrive() {
        final String unionID = HmsProxyImpl.getInstance().getUnionId();
        final String at = HmsProxyImpl.getInstance().getAccessToken();
        TaskManager.getInstance().execute(new Task() {
            @Override
            public void call() {
                int returnCode = CredentialManager.getInstance().init(unionID, at, refreshAT);
                // go to the main activity
                ....
            }
        });
    }
}
public class HmsProxyImpl {
    private HuaweiIdAuthParams signInOptions;
    private static HmsProxyImpl instance = new HmsProxyImpl();
    public static final int REQUEST_SIGN_IN_LOGIN = 1002;
    private ReentrantLock getATLock = new ReentrantLock();
    private HuaweiIdAuthService client;
    private String accessToken;
    private String unionId;
    private Activity activity;
    private HmsProxyImpl() {
        signInOptions = initData();
    }
    public static HmsProxyImpl getInstance() {
        return instance;
    }
    private HuaweiIdAuthParams initData() {
        List<Scope> scopeList = new LinkedList<>(Arrays.asList(
                HuaweiIdAuthAPIManager.HUAWEIID_BASE_SCOPE,
                new Scope(DriveScopes.SCOPE_DRIVE),
                new Scope(DriveScopes.SCOPE_DRIVE_METADATA),
                new Scope(DriveScopes.SCOPE_DRIVE_FILE),
                new Scope(DriveScopes.SCOPE_DRIVE_APPDATA)));
        HuaweiIdAuthParams authParams = new HuaweiIdAuthParamsHelper(HuaweiIdAuthParams.DEFAULT_AUTH_REQUEST_PARAM)
                .setScopeList(scopeList)        
                .setIdToken()        
                .setAccessToken()        
                .createParams();
        return authParams ;
    }
    public void signIn(Activity activity) {
        this.activity = activity;
        if (signInOptions == null) {
            signInOptions = initData();
        }
        client = HuaweiIdAuthManager.getService(activity, signInOptions);
        activity.startActivityForResult(client.getSignInIntent(), REQUEST_SIGN_IN_LOGIN);
    }
    public String refreshAccessToken() {
        try {
            if (client != null) {
                getATLock.lock();
                try {
                    getAT();
                } finally {
                    getATLock.unlock();
                }
            } 
        } catch (Exception e) {
            // deal Exception
        }
        return accessToken;
    }
    private void getAT() {
        for (int retry = 0; retry < 2; retry++) {
            if (signInBackend()) {
                break;
            }
        }
    }
    private boolean signInBackend(){
        clearAccountInfo();
        final CountDownLatch countDownLatch = new CountDownLatch(1);
        com.huawei.hmf.tasks.Task<AuthHuaweiId> task = client.silentSignIn();
        task.addOnSuccessListener(new OnSuccessListener<AuthHuaweiId>() {
            @Override
            public void onSuccess(AuthHuaweiId signInHuaweiId) {
                dealSignInResult(signInHuaweiId);
                countDownLatch.countDown();
            }
        });
        task.addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(Exception e) {
                countDownLatch.countDown();
            }
        });
        try {
            countDownLatch.await(15, TimeUnit.SECONDS);
        }catch (InterruptedException e) {
            countDownLatch.countDown();
        }
        if (TextUtils.isEmpty(getAccessToken())) {
            return false;
        } else {
            return true;
        }
    }
    public void dealSignInResult(AuthHuaweiId huaweiAccount){
        String tempAt = huaweiAccount.getAccessToken();
        if (null == tempAt || tempAt.isEmpty()) {
            return;
        }
        saveAccountInfo(huaweiAccount);
    }
    private void saveAccountInfo(AuthHuaweiId signInHuaweiId) {
        if (signInHuaweiId == null) {
            return;
        }
        unionId = signInHuaweiId.getUnionId();
        accessToken = signInHuaweiId.getAccessToken();
    }
    private void clearAccountInfo() {
        unionId = null;
        accessToken = null;
    }
    public String getAccessToken() {
        return this.accessToken;
    }
    public String getUnionId() {
        return unionId;
    }
}
public class CredentialManager {
    /**
     * Drive credential authorization
     */
    private DriveCredential mCredential;
    private CredentialManager() {
    }
    private static class InnerHolder {
        private static CredentialManager sInstance = new CredentialManager();
    }
    public static CredentialManager getInstance() {
        return InnerHolder.sInstance;
    }
    /**
     * init the drive sdk with access token and HwId Account info,
     * register a AccessMethod to get a new accessToken while accessToken is expired.
     *
     * @param unionID   unionID from HwID
     * @param at        access token
     * @param refreshAT a callback to refresh AT
     */
    public int init(String unionID, String at, DriveCredential.AccessMethod refreshAT) {
        if (StringUtils.isNullOrEmpty(unionID) || StringUtils.isNullOrEmpty(at)) {
            return DriveCode.ERROR;
        }
        DriveCredential.Builder builder = new DriveCredential.Builder(unionID, refreshAT);
        mCredential = builder.build().setAccessToken(at);
        return DriveCode.SUCCESS;
    }
    public DriveCredential getCredential() {
        return mCredential;
    }
}

字符串替换

[h2]文件的mimeType字段值替换

全量搜索App项目中的“application/vnd.google-apps.folder”字符串,将其替换为“application/vnd.huawei-apps.folder”,如下:

[h2]文件查询目录时的查询参数“in parents”替换

查询文件时候,通过文件名排序,将parentFileId + “in parents”替换为parentFileId + “in parentFolder”。

  1. 查询云盘根目下的文件及文件夹,parentFileId用'root'替代,如下:

  2. 查询非云盘根目下的文件及文件夹,parentFileId(需要用单引号包裹,如:'AgMhP8hcDTQDvvVzWeHZeJIO9X9Z7A04A')是一个真实的目录ID,如下:

[h2]文件排序参数--文件名替换

查询文件时候,通过文件名排序,将“name”替换为“fileName”,如下:

[h2]文件排序参数--修改时间替换

查询文件的时候,通过修改时间排序,将“modifiedTime”替换为“editedTime”,如下:

[h2]文件查询参数--回收站标识字段值替换

查询文件时候,通过回收站标识字段过滤,将“trashed”替换为“recycled”,如下:

[h2]查询范围参数替换

将“appDataFolder”替换为“applicationData”,如下:

Drive实例化

Google API中的Drive构造器跟HMS的完全不同,需要手工替换。

Drive的构造需要在登录时初始化Credential信息,HMS和Google API初始化Credential的内容请参见登录方式变更。

Google API

To HMS API

Drive(com.google.api.client.http.HttpTransport transport, com.google.api.client.json.JsonFactory jsonFactory, com.google.api.client.http.HttpRequestInitializer httpRequestInitializer)

public Drive(com.huawei.cloud.base.auth.DriveCredential credential, android.content.Context context)

具体实现请参见Drive。

Google API示例:
public class DriveQuickstart {
    private static final String APPLICATION_NAME = "Google Drive API Java Quickstart";
    private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
    private static final String TOKENS_DIRECTORY_PATH = "tokens";

    /**
    * Global instance of the scopes required by this quickstart.
    * If modifying these scopes, delete your previously saved tokens/ folder.
    */
    private static final List<String> SCOPES =  Collections.singletonList(DriveScopes.DRIVE_METADATA_READONLY);
    private static final String CREDENTIALS_FILE_PATH = "/credentials.json";

    /**
    * Creates an authorized Credential object.
    * @param HTTP_TRANSPORT The network HTTP Transport.
    * @return An authorized Credential object.
    * @throws IOException If the credentials.json file cannot be found.
    */
    private static Credential getCredentials(final NetHttpTransport HTTP_TRANSPORT) throws IOException {
        // Load client secrets.
        InputStream in = DriveQuickstart.class.getResourceAsStream(CREDENTIALS_FILE_PATH);
        if (in == null) {
            throw new FileNotFoundException("Resource not found: " + CREDENTIALS_FILE_PATH);
        }
        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(new FileDataStoreFactory(new java.io.File(TOKENS_DIRECTORY_PATH)))
            .setAccessType("offline")
            .build();
        LocalServerReceiver receiver = new LocalServerReceiver.Builder().setPort(8888).build();
        return new AuthorizationCodeInstalledApp(flow, receiver).authorize("user");
    }

    public static void main(String... args) throws IOException, GeneralSecurityException {
        // Build a new authorized API client service.
        final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
        Drive service = new Drive.Builder(HTTP_TRANSPORT, JSON_FACTORY, getCredentials(HTTP_TRANSPORT))
                .setApplicationName(APPLICATION_NAME)
                .build();    
    }
}

替换成的HMS API示例:

public Drive buildDrive(Context context) {
    DriveCredential credential = CredentialManager.getInstance().getCredential();
    if (credential == null || context == null) {     
        return null;
    }
    return new Drive.Builder(credential, context).build();
}

Drive.Builder实例化

Google API中的Drive.Builder构造器跟HMS的完全不同,需要手工替换。

Drive.Builder的构造需要在登录时初始化Credential信息,HMS和Google API初始化credential的内容请参见登录方式变更。

Google API

To HMS API

public Builder(com.google.api.client.http.HttpTransport transport, com.google.api.client.json.JsonFactory jsonFactory, com.google.api.client.http.HttpRequestInitializer httpRequestInitializer)

public Builder(com.huawei.api.huaweiapis.auth.DriveCredential credential, android.content.Context context)

具体实现请参见Drive.Builder。

Google API示例:

public class DriveQuickstart {
    private static final String APPLICATION_NAME = "Google Drive API Java Quickstart";
    private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
    private static final String TOKENS_DIRECTORY_PATH = "tokens";

    /**
    * Global instance of the scopes required by this quickstart.
    * If modifying these scopes, delete your previously saved tokens/ folder.
    */
    private static final List<String> SCOPES =  Collections.singletonList(DriveScopes.DRIVE_METADATA_READONLY);
    private static final String CREDENTIALS_FILE_PATH = "/credentials.json";

    /**
    * Creates an authorized Credential object.
    * @param HTTP_TRANSPORT The network HTTP Transport.
    * @return An authorized Credential object.
    * @throws IOException If the credentials.json file cannot be found.
    */
    private static Credential getCredentials(final NetHttpTransport HTTP_TRANSPORT) throws IOException {
        // Load client secrets.
        InputStream in = DriveQuickstart.class.getResourceAsStream(CREDENTIALS_FILE_PATH);
        if (in == null) {
            throw new FileNotFoundException("Resource not found: " + CREDENTIALS_FILE_PATH);
        }
        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(new FileDataStoreFactory(new java.io.File(TOKENS_DIRECTORY_PATH)))
            .setAccessType("offline")
            .build();
        LocalServerReceiver receiver = new LocalServerReceiver.Builder().setPort(8888).build();
        return new AuthorizationCodeInstalledApp(flow, receiver).authorize("user");
    }

    public static void main(String... args) throws IOException, GeneralSecurityException {
        // Build a new authorized API client service.
        final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
        Drive.Builder builder= new Drive.Builder(HTTP_TRANSPORT, JSON_FACTORY, getCredentials(HTTP_TRANSPORT));
    }
}

HMS API示例:

public Drive.Builder getBuilder(Context context) {
    DriveCredential credential = CredentialManager.getInstance().getCredential();
    if (credential == null || context == null) {     
        return null;
    }
    return new Drive.Builder(credential, context);
}

setMd5Checksum(java.lang.String)替换方法

方法一:直接删除,因为客户端可以不主动设置Sha256的值,服务器会自动生成。

方法二:用setSha256(java.lang.String sha256)替换,如下:

Google API 示例:

String md5Checksum = "******************";
***.setMd5Checksum(md5Checksum);

替换后的HMS API 示例:

// 使用标准的Sha256算法计算出一个值,并通过Sha256属性进行设置。
String sha256 = "******************";
***.setSha256(sha256);

setUserIp(java.lang.String)替代方法

com.google.api.services.drive.DriveRequest<T>类及其子类中的setUserIp(java.lang.String)方法替代如下:

Google API示例:

Drive drive;  // 该变量由您初始化,可以参见Drive实例化
Drive.About about = drive.about();
Drive.About.Get request = null;
try {    
    request = about.get();    
    request.setUserIp("10.12.10.1");} 
catch (IOException e) {    
    Log.e(TAG, "about.get() failed, exception: " + e.toString());
}

替换后的HMS API示例:

Drive drive;  // 该变量由您初始化,可以参见Drive实例化
Drive.About about = drive.about();
Drive.About.Get request = null;
try {    
    request = about.get();
    // A user-defined function generates a string of less than 40 characters,which is used to represent the user, and the string generated by each user cannot be repeated
    String quotaId = StringUtil.randomString();
    request.setQuotaId(quotaId);} 
catch (IOException e) {    
    Log.e(TAG, "about.get() failed, exception: " + e.toString());
}

Permission.setEmailAddress(java.lang.String emailAddress)替代方法

Google API示例:

Permission permission = new Permission();
permission.setEmailAddress("example@***.com");

替换后的HMS API示例:

Permission permission = new Permission();
permission.setUserAccount("example@***.com");
/** 
 * 设置帐号类型,详情请参见Permission.setAccountType()指南。
 * 目前枚举值有"0"、"1"、"2"("0"对应default、"1"对应email、"2"对应phoneNo)。
 */
permission.setAccountType("1");