1

我有一個Android應用程序,應該使用谷歌融合表。我使用的是Google服務帳戶,必須獲取我的xxxxxxxxxxxprivatekey.p12的路徑。Android的NetworkOnMainThreadException在谷歌Credential.refreshToken()

public class CredentialProvider { 

... 

private static String PRIVATE_KEY = "xxxxxxxxxxxprivatekey.p12"; 

... 

public static GoogleCredential getCredential() throws IOException, GeneralSecurityException {   
     return getCredential(Arrays.asList(SCOPES), SERVICE_ACCOUNT_EMAIL, new File(PRIVATE_KEY), HTTP_TRANSPORT, JSON_FACTORY); 
    } 

... 

} 

該代碼想從PRIVATE_KEY路徑中創建一個新文件。我嘗試了各種路徑,但每次我收到FileNotFoundExceptionopen failed: ENOENT (No such file or directory)

我已閱讀關於資產文件夾的一些信息,但我不知道如何使用getCredential方法獲得該工作。

  • 哪裏我已經把我的私人密鑰在我的Android項目
  • 如何有看起來像
  • 我如何獲得「新的文件(PRIVATE_KEY)」的PRIVATE_KEY路徑工作

感謝;)


編輯:

現在我重寫GoogleCredential.Builder在您的鏈接創建自己的setServiceAccountPrivateKeyFromP12File(InputStream p12File)喜歡它似乎很好地工作。但在getCredential()refreshToken()被調用並崩潰在NetworkOnMainThreadException。 我讀過,我應該使用AsyncTask它。你能給我一個提示,,我必須把那個AsyncTask什麼應該在doInBackground()onPostExecute()或什麼方法裏面?

這是getCredential()的代碼。它崩潰的refreshToken()NetworkOnMainThreadException

public static GoogleCredential getCredential(List<String> SCOPE, String SERVICE_ACCOUNT_EMAIL, 
      InputStream inputStreamFromP12File, HttpTransport HTTP_TRANSPORT, JsonFactory JSON_FACTORY) 
      throws IOException, GeneralSecurityException {   
     // Build service account credential. 

     MyGoogleCredentialBuilder builder = new MyGoogleCredentialBuilder(); 
     builder.setTransport(HTTP_TRANSPORT); 
     builder.setJsonFactory(JSON_FACTORY); 
     builder.setServiceAccountId(SERVICE_ACCOUNT_EMAIL); 
     builder.setServiceAccountScopes(SCOPE); 
     builder.setServiceAccountPrivateKeyFromP12File(inputStreamFromP12File); 

     GoogleCredential credential = builder.build(); 

     credential.refreshToken(); 
     return credential; 
    } 

EDIT2: 最後,我解決了這樣的說法:

private static class RefreshTokenTask extends AsyncTask<GoogleCredential, Void, Void> { 
     @Override 
     protected Void doInBackground(GoogleCredential... params) { 
      try { 
       params[0].refreshToken(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
      return null; 
     } 
    } 

,並在我的getCredential方法:

new RefreshTokenTask().execute(credential); 
+0

您可以使自己的版本,這需要一個InputStream,你可以從資產獲得 - 看https://code.google.com/p/google-api-java-client/issues/細節?id = 857 –

+0

謝謝,這看起來更好。但是我必須把這個方法放在哪裏呢?我無法查看或編輯'com.google.api.client.googleapis.auth.oauth2.GoogleCredential.Builder'中的代碼。 – rillner

+0

@ChrisStratton查看我的編輯。 – rillner

回答

1

您無法像訪問常規文件那樣訪問資產,因爲這些文件與應用程序捆綁在一起。 這就是爲什麼new File(PRIVATE_KEY)不起作用,並且沒有可以讓它工作的路徑。

你可以做的是得到一個InputStream該文件:

AssetManager assetManager = context.getAssets(); 
InputStream input = assetManager.open(PRIVATE_KEY); 

如果您需要訪問它作爲一個文件,你可以把它複製到你的應用程序的內部存儲的應用程序第一次是推出。我不確定這是最好的解決方案(出於安全原因,您可能不希望將私鑰存儲在設備的內部存儲上),但它應該可以工作。然後您可以從context.getFilesDir()文件夾訪問它。

InputStream fis = assetManager.open(PRIVATE_KEY); 
FileOutputStream fos = openFileOutput(PRIVATE_KEY, Context.MODE_PRIVATE); 
byte buf[] = new byte[1024]; 
int len; 
while ((len = fis.read(buf)) > 0) { 
    fos.write(buf, 0, len); 
} 
fis.close(); 
fos.close(); 
+0

謝謝你的回答。無論如何,我**需要**我的私鑰的java.io.File對象,因爲我必須調用google api的'setServiceAccountPrivateKeyFromP12File(File p12File)'。有什麼辦法可以得到嗎? – rillner

+0

@ captainchaos91查看我的編輯 – Eran

+0

@ChrisStratton感謝您的評論。我最初寫道,使用外部存儲可能不是一個好的主意,並且像你所說的那樣使用內部存儲更好。我更新了答案。 – Eran