Я пытаюсь подключить свое приложение Android к Google Calendars. Я следовал учебному пособию quick start , попросил у пользователя разрешения на запись во внешнее хранилище, но я не могу запустить код, не выдав исключение java .io.IOException.
Мой код выглядит следующим образом:
GoogleCalendarModule.kt
class GoogleCalendarModule {
var APPLICATION_NAME: String = "Conglobo"
var JSON_FACTORY: JacksonFactory = JacksonFactory.getDefaultInstance()
var TOKENS_DIRECTORY_PATH: String = "./tokens"
var SCOPES: List<String> = Collections.singletonList(CalendarScopes.CALENDAR_READONLY)
private var CREDENTIALS_FILE_PATH: String = "/credentials.json"
fun getCredentials(HTTP_TRANSPORT: NetHttpTransport): com.google.api.client.auth.oauth2.Credential? {
val inputStream: InputStream = this.javaClass.getResourceAsStream(CREDENTIALS_FILE_PATH)
?: throw FileNotFoundException("Resource Not found: $CREDENTIALS_FILE_PATH")
val clientSecrets: GoogleClientSecrets = GoogleClientSecrets.load(JSON_FACTORY, InputStreamReader(inputStream))
val tokenFolder = File(getExternalStorageDirectory(), File.separator.toString() + TOKENS_DIRECTORY_PATH)
if (!tokenFolder.exists()) {
tokenFolder.mkdirs()
}
val flow: GoogleAuthorizationCodeFlow = GoogleAuthorizationCodeFlow.Builder(
HTTP_TRANSPORT, JSON_FACTORY, clientSecrets, SCOPES)
.setDataStoreFactory(FileDataStoreFactory(tokenFolder))
.setAccessType("offline")
.build();
val receiver: LocalServerReceiver = LocalServerReceiver.Builder().setPort(8888).build()
return AuthorizationCodeInstalledApp(flow, receiver).authorize("user")
}
fun doSomething() {
val HTTP_TRANSPORT = NetHttpTransport()
val service: Calendar = Calendar.Builder(HTTP_TRANSPORT, JSON_FACTORY, getCredentials(HTTP_TRANSPORT))
.setApplicationName(APPLICATION_NAME)
.build()
val now = DateTime(System.currentTimeMillis())
val events: Events = service.events().list("primary")
.setMaxResults(10)
.setTimeMin(now)
.setOrderBy("startTime")
.setSingleEvents(true)
.execute()
val items: List<Event> = events.items
if (items.isEmpty()) {
println("No events")
} else {
println("Upcoming events")
for(event: Event in items) {
var start: DateTime = event.start.dateTime
if(start == null) {
start = event.start.date
}
print(event.summary)
}
}
}
}
Затем я проверяю текущие разрешения в MainActivity
MainActivity.kt
class MainActivity: AppCompatActivity(), ITeamFragmentDelegate {
@Inject
lateinit var teamInfoModule: TeamInfoModule;
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED) {
print("Permission is granted");
} else {
print("Permission is revoked");
ActivityCompat.requestPermissions(this, Array<String>(1) { Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
}
}
GoogleCalendarModule().doSomething()
setContentView(R.layout.activity_main)
DaggerServiceModuleComponent.create().inject(this)
val teamArrayList: ArrayList<Team> = this.teamInfoModule.getAllTeamData()
for(team: Team in teamArrayList) {
val bundle = Bundle()
val teamFragment = TeamFragment()
bundle.putParcelable("teamData", team)
teamFragment.arguments = bundle
supportFragmentManager.beginTransaction()
.add(R.id.root_container, teamFragment)
.commitAllowingStateLoss()
}
}
override fun onTeamClicked(fragment: TeamFragment, team: Team) {
val intent = Intent(this, ViewTeamBacklogActivity::class.java)
intent.putExtra("teamId", team.id)
startActivity(intent)
}
}
И у меня даже есть разрешения, объявленные в AndroidManifest. xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.bluelightlite">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".ViewTeamBacklogActivity">
</activity>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Я искал вокруг SO, и это, кажется, общая проблема, но ни одно из решений, которые я ' мы нашли работали. Может ли кто-нибудь помочь, пожалуйста?