Так что я понятия не имею, что произошло, но я очистил свой проект, и код сработал ... Он выглядит следующим образом:
class GoogleCalendarsServiceModule constructor(context: Context) {
private val googleCredential: Credential
private val httpTransport: NetHttpTransport = NetHttpTransport()
private val googleCredentialsUtilityModule = GoogleCredentialsUtilityModule(context)
private var googleCalendarService: Calendar
init {
this.googleCredential = this.googleCredentialsUtilityModule.execute(this.httpTransport).get()
this.googleCalendarService = ServiceBuilder().buildGoogleCalendarService(this.googleCredential, this.httpTransport)
}
/**
* gets all calendar events
* @see - https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-dispatchers/-i-o.html
* @return Events list
*/
suspend fun getCalendarEvents(): List<Event> = withContext(Dispatchers.IO) {
val now = DateTime(System.currentTimeMillis())
val events: Calendar.Events? = googleCalendarService.events()
val allEvents = events!!.list("primary")
.setMaxResults(10)
.setTimeMin(now)
.setOrderBy("startTime")
.setSingleEvents(true)
.execute()
allEvents.items
}
suspend fun getCalendarEventsForRoom(roomName: String): List<Event> = withContext(Dispatchers.IO) {
val now = DateTime(System.currentTimeMillis())
val events: Calendar.Events? = googleCalendarService.events()
val allEventsForRoom = events!!.list("primary")
.setMaxResults(10)
.setTimeMin(now)
.setOrderBy("startTime")
.setSingleEvents(true)
.execute()
allEventsForRoom.items.distinctBy { x -> x.location == roomName }
}
}
Модуль учетных данных, который устанавливает и поддерживает учетные данные Google 0Auth. Включая настройку папки токенов, если она отсутствует.
class GoogleCredentialsUtilityModule constructor(private val context: Context): AsyncTask<NetHttpTransport, Void, Credential>() {
/**
* Starts getting credentials on a different thread by implementing
* AsyncTask<>()
* @param params: a list of parameters
* @return none
*/
override fun doInBackground(vararg params: NetHttpTransport): Credential {
return this.getCredentials(params[0])
}
/**
* Creates an authorized Credential object.
* @param HTTP_TRANSPORT The network HTTP Transport.
* @return An authorized Credential object.
* @throws java.io.IOException If the credentials.json file cannot be found.
*/
private fun getCredentials(HTTP_TRANSPORT: NetHttpTransport): Credential {
val inputStream: InputStream = getCredentialsAsInputStream()
val clientSecrets: GoogleClientSecrets = GoogleClientSecrets.load(JSON_FACTORY, InputStreamReader(inputStream))
createTokenFolderIfMissing()
val authorisationFlow: GoogleAuthorizationCodeFlow = getAuthorisationFlow(HTTP_TRANSPORT, clientSecrets)
val localServerReceiver: LocalServerReceiver = LocalServerReceiver.Builder().setPort(43783).build()
val ab: AuthorizationCodeInstalledApp =
object : AuthorizationCodeInstalledApp(authorisationFlow, localServerReceiver) {
@Throws(IOException::class)
override fun onAuthorization(authorizationUrl: AuthorizationCodeRequestUrl) {
val url = authorizationUrl.build()
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
context.startActivity(browserIntent)
}
}
return ab.authorize("user")
}
/**
* Gets the /credentials.json file
* @return InputStream
*/
private fun getCredentialsAsInputStream(): InputStream {
return this.javaClass.getResourceAsStream(CREDENTIALS_FILE_PATH)
?: throw FileNotFoundException("Resource Not found: $CREDENTIALS_FILE_PATH")
}
/**
* Creates the Tokens Folder for Google Authentication
* Uses the current context for the folder path from
* Context.getExternalFilesDir()
*/
private fun createTokenFolderIfMissing() {
val tokenFolder = getTokenFolder()
if (!tokenFolder.exists()) {
tokenFolder.mkdir()
}
}
/**
* gets External storage directory from the
* current context
* @return File
*/
private fun getTokenFolder(): File {
return File(this.context.getExternalFilesDir("")?.absolutePath + TOKENS_DIRECTORY_PATH)
}
/**
* Gets authorisation flow so that the application can authenticate into Google Calendars
* @param HTTP_TRANSPORT allows the app to use HTTP connections
* @param clientSecrets secrets for authentication into Google
* @return GoogleAuthorizationCodeFlow
*/
private fun getAuthorisationFlow(HTTP_TRANSPORT: NetHttpTransport, clientSecrets: GoogleClientSecrets): GoogleAuthorizationCodeFlow {
return GoogleAuthorizationCodeFlow.Builder(
HTTP_TRANSPORT, JSON_FACTORY, clientSecrets, SCOPES)
.setDataStoreFactory(FileDataStoreFactory(getTokenFolder()))
.setAccessType("offline")
.build()
}
}
И, наконец, вызов службы с использованием сопрограммы:
class MainActivity : AppCompatActivity(), CoroutineScope, IMeetingRoomDelegate {
private var job: Job = Job()
override val coroutineContext: CoroutineContext
get() = Dispatchers.Main + job
@Inject
lateinit var permissionsUtilityModule: PermissionsUtilityModule
private lateinit var googleCalendarsServiceModule: GoogleCalendarsServiceModule
private lateinit var meetingRooms: MeetingRooms
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
DaggerUtilityModuleComponent.create().inject(this)
this.permissionsUtilityModule.checkUserPermissions(this)
this.googleCalendarsServiceModule = GoogleCalendarsServiceModule(this);
launch {
val events: List<Event> = googleCalendarsServiceModule.getCalendarEvents()
meetingRooms = setMeetingRooms(events)
setMeetingRoomFragments(meetingRooms)
}
setContentView(R.layout.activity_main)
}
override fun onDestroy() {
super.onDestroy()
this.job.cancel()
}
override fun onMeetingRoomFragmentClicked(fragment: MeetingRoomFragment, meetingRoom: MeetingRoom) {
val intent = Intent(this, ViewMeetingRoomDataActivity::class.java)
intent.putExtra("meetingRoomData", meetingRoom)
startActivity(intent)
}
private fun setMeetingRooms(events: List<Event>): MeetingRooms {
val mappedEvents: List<MeetingEvent> = mapMeetingEvents(events)
val meetingEvents = MeetingEvents(mappedEvents)
return MeetingRoomFactory().getRooms(meetingEvents)
}
private fun setMeetingRoomFragments(mappedMeetingRooms: MeetingRooms) {
for(meetingRoom: MeetingRoom in mappedMeetingRooms.getMeetingRooms()) {
val bundle = Bundle()
val meetingRoomFragment = MeetingRoomFragment()
bundle.putParcelable("meetingRoomData", meetingRoom)
meetingRoomFragment.arguments = bundle
supportFragmentManager.beginTransaction()
.add(R.id.root_container, meetingRoomFragment)
.commitAllowingStateLoss()
}
}
}
Мысль, которую я опубликую, если кому-то понадобится помощь с весь 0Auth rigmarole.