diff --git a/app/build.gradle b/app/build.gradle index ff0cedb3..0fdb7c36 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -36,6 +36,17 @@ android { androidExtensions { experimental = true } + + packagingOptions { + exclude 'META-INF/DEPENDENCIES' + exclude 'META-INF/LICENSE' + exclude 'META-INF/LICENSE.txt' + exclude 'META-INF/license.txt' + exclude 'META-INF/NOTICE' + exclude 'META-INF/NOTICE.txt' + exclude 'META-INF/notice.txt' + exclude 'META-INF/ASL2.0' + } } dependencies { @@ -79,3 +90,14 @@ apply plugin: 'com.google.gms.google-services' dependencies { implementation 'com.android.support.constraint:constraint-layout:1.1.3' } + +dependencies { + implementation 'com.google.android.gms:play-services-auth:15.0.1' + implementation 'com.google.http-client:google-http-client-gson:1.28.0' + implementation('com.google.api-client:google-api-client-android:1.28.0') { + exclude group: 'org.apache.httpcomponents' + } + implementation('com.google.apis:google-api-services-drive:v3-rev136-1.25.0') { + exclude group: 'org.apache.httpcomponents' + } +} diff --git a/app/src/main/java/ru/spb/speech/SettingsActivity.kt b/app/src/main/java/ru/spb/speech/SettingsActivity.kt index b5b2a1f5..b74cc423 100644 --- a/app/src/main/java/ru/spb/speech/SettingsActivity.kt +++ b/app/src/main/java/ru/spb/speech/SettingsActivity.kt @@ -2,6 +2,7 @@ package ru.spb.speech import android.annotation.SuppressLint import android.annotation.TargetApi +import android.app.Activity import android.app.AlarmManager import android.app.PendingIntent import android.content.ComponentName @@ -17,6 +18,7 @@ import android.preference.* import android.text.TextUtils import android.util.Log import android.view.MenuItem +import ru.spb.speech.appSupport.GoogleDriveHelper import ru.spb.speech.notifications.AlarmBootReceiver import ru.spb.speech.notifications.AlarmReceiver import ru.spb.speech.notifications.NotificationsHelper @@ -52,6 +54,12 @@ class SettingsActivity : AppCompatPreferenceActivity() { override fun onOptionsItemSelected(item: MenuItem): Boolean { val id = item.itemId if (id == android.R.id.home) { + val driveFolderId = PreferenceManager + .getDefaultSharedPreferences(this) + .getString(getString(R.string.drive_folder_key), "") + if (driveFolderId != null && driveFolderId != "") + GoogleDriveHelper.getInstance().requestSignIn(this) + onBackPressed() return true } @@ -103,6 +111,7 @@ class SettingsActivity : AppCompatPreferenceActivity() { bindPreferenceSummaryToValue(findPreference("example_list")) bindPreferenceSummaryToValue(findPreference(getString(R.string.speed_key))) bindPreferenceSummaryToValue(findPreference("statistics_collection")) + bindPreferenceSummaryToValue(findPreference(getString(R.string.drive_folder_key))) } override fun onOptionsItemSelected(item: MenuItem): Boolean { @@ -219,6 +228,18 @@ class SettingsActivity : AppCompatPreferenceActivity() { } } + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + super.onActivityResult(requestCode, resultCode, data) + + if (resultCode == Activity.RESULT_OK) { + when (requestCode) { + GoogleDriveHelper.REQUEST_CODE_SIGN_IN -> { + GoogleDriveHelper.getInstance().heldSignInResult(this, data) + } + } + } + } + companion object { /** @@ -314,7 +335,6 @@ class SettingsActivity : AppCompatPreferenceActivity() { .getDefaultSharedPreferences(preference.context) .getString(preference.key, "")) } - } } } diff --git a/app/src/main/java/ru/spb/speech/StartPageActivity.kt b/app/src/main/java/ru/spb/speech/StartPageActivity.kt index 031de9f9..ff613485 100644 --- a/app/src/main/java/ru/spb/speech/StartPageActivity.kt +++ b/app/src/main/java/ru/spb/speech/StartPageActivity.kt @@ -26,6 +26,7 @@ import kotlinx.android.synthetic.main.activity_start_page.* import ru.spb.speech.appSupport.* import ru.spb.speech.measurementAutomation.RunningTraining import java.io.File +import kotlin.collections.ArrayList const val debugSpeechAudio = R.raw.assembler // Путь к файлу в raw, // который запускается в виде тестовой звуковой дорожки. @@ -100,6 +101,12 @@ class StartPageActivity : AppCompatActivity(), UpdateAdapterListener { val intent = Intent(this, CreatePresentationActivity::class.java) startActivity(intent) } + + val driveFolderId = PreferenceManager + .getDefaultSharedPreferences(this) + .getString(getString(R.string.drive_folder_key), "") + if (driveFolderId != null && driveFolderId != "") + GoogleDriveHelper.getInstance().requestSignIn(this) } override fun onStart() { @@ -214,6 +221,10 @@ class StartPageActivity : AppCompatActivity(), UpdateAdapterListener { Log.d(RunningTraining.LOG, data?.data?.toString()) testFolderRunner?.startTrainings(DocumentFile.fromTreeUri(this, selectedFile!!)!!) } + + GoogleDriveHelper.REQUEST_CODE_SIGN_IN -> { + GoogleDriveHelper.getInstance().heldSignInResult(this, data) + } } } } diff --git a/app/src/main/java/ru/spb/speech/appSupport/AudioAnalyzer.kt b/app/src/main/java/ru/spb/speech/appSupport/AudioAnalyzer.kt index e08d05a1..fd1505c5 100644 --- a/app/src/main/java/ru/spb/speech/appSupport/AudioAnalyzer.kt +++ b/app/src/main/java/ru/spb/speech/appSupport/AudioAnalyzer.kt @@ -256,6 +256,7 @@ class AudioAnalyzer(private val activity: Activity, controller: MutableLiveData< logStatistics() saveFile(byteArrayOutputStream) + GoogleDriveHelper.getInstance().saveFileToDrive(activity, byteArrayOutputStream) } } diff --git a/app/src/main/java/ru/spb/speech/appSupport/GoogleDriveHelper.kt b/app/src/main/java/ru/spb/speech/appSupport/GoogleDriveHelper.kt new file mode 100644 index 00000000..19c817c1 --- /dev/null +++ b/app/src/main/java/ru/spb/speech/appSupport/GoogleDriveHelper.kt @@ -0,0 +1,131 @@ +package ru.spb.speech.appSupport + +import android.app.Activity +import android.content.Intent +import android.preference.PreferenceManager +import android.util.Log +import android.widget.Toast +import com.google.android.gms.auth.api.signin.GoogleSignIn +import com.google.android.gms.auth.api.signin.GoogleSignInOptions +import com.google.android.gms.common.api.Scope +import com.google.api.client.extensions.android.http.AndroidHttp +import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential +import com.google.api.client.http.ByteArrayContent +import com.google.api.client.json.gson.GsonFactory +import com.google.api.services.drive.Drive +import com.google.api.services.drive.DriveScopes +import ru.spb.speech.R +import java.io.ByteArrayOutputStream +import java.text.SimpleDateFormat +import java.util.* + + +const val DRIVE_TAG = "GOOGLE_DRIVE_TAG" + +class GoogleDriveHelper { + companion object { + const val REQUEST_CODE_SIGN_IN = 0 + + private val driveHelper = GoogleDriveHelper() + + fun getInstance() = driveHelper + } + + var driveService: Drive? = null + var accountName = "Unnamed" + + fun requestSignIn(activity: Activity) { + Log.d(DRIVE_TAG, "Requesting sign-in") + + if (driveService == null) { + val signInOptions = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) + .requestEmail() + .requestScopes(Scope(DriveScopes.DRIVE_FILE)) + .build() + val client = GoogleSignIn.getClient(activity, signInOptions) + + Log.d(DRIVE_TAG, "Starting activity for result") + activity.startActivityForResult(client.signInIntent, REQUEST_CODE_SIGN_IN) + } else { + Log.d(DRIVE_TAG, "Already signed in") + } + } + + fun heldSignInResult(activity: Activity, data: Intent?) { + GoogleSignIn.getSignedInAccountFromIntent(data) + .addOnSuccessListener { googleAccount -> + Log.d(DRIVE_TAG, "Logged in successfully") + + val name = googleAccount.displayName + if (name != null) + accountName = name + else { + accountName = "Unnamed" + Log.e(DRIVE_TAG, "Failed getting google account name") + Toast.makeText(activity, + "Ошибка при получении имени из Google-аккаунта", + Toast.LENGTH_SHORT).show() + } + + Log.d(DRIVE_TAG, "Signed in as $name") + Toast.makeText(activity, "Вы вошли в Google как $name", Toast.LENGTH_SHORT) + .show() + + val credential = GoogleAccountCredential.usingOAuth2( + activity, Collections.singleton(DriveScopes.DRIVE_FILE)) + credential.setSelectedAccount(googleAccount.account) + val googleDriveService = Drive.Builder( + AndroidHttp.newCompatibleTransport(), + GsonFactory(), + credential) + .setApplicationName("Drive API Migration") + .build() + + driveService = googleDriveService + Log.d(DRIVE_TAG, "Drive service is ready") + } + .addOnFailureListener { exception -> + Log.e(DRIVE_TAG, "Unable to sign in.", exception) + Toast.makeText(activity, "Ошибка при входе в Google-аккаунт", + Toast.LENGTH_SHORT).show() + } + } + + fun saveFileToDrive(activity: Activity, byteArrayOutputStream: ByteArrayOutputStream) { + if (driveService != null) { + val driveService = (driveService as Drive) + + val parentId = PreferenceManager + .getDefaultSharedPreferences(activity) + .getString(activity.getString(R.string.drive_folder_key), "root") + if (parentId == null) { + Log.e(DRIVE_TAG, "Error while getting folder id from preferences") + Toast.makeText(activity, "Ошибка при получении ID папки Google-диска из настроек", + Toast.LENGTH_SHORT).show() + } + + val fileName = "$accountName " + + SimpleDateFormat.getDateTimeInstance().format(Date()) + ".wav" + + var metadata = com.google.api.services.drive.model.File() + .setParents(Collections.singletonList(parentId)) + .setMimeType("audio/vnd.wave") + .setName(fileName) + + val resultFile = driveService.files().create(metadata).execute() + if (resultFile == null) { + Log.e(DRIVE_TAG, "Null result when creating file") + Toast.makeText(activity, "Ошибка при создании файла на Google-диске", + Toast.LENGTH_SHORT).show() + return + } + + metadata = com.google.api.services.drive.model.File().setName(fileName) + + val mediaContent = ByteArrayContent.fromString("audio/vnd.wave", byteArrayOutputStream.toString()) + driveService.files().update(resultFile.id, metadata, mediaContent).execute() + + Log.d(DRIVE_TAG, "File saved") + } + } +} \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index adcfe36e..1e796fed 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -361,6 +361,8 @@ увеличить время выступления. Отсутствие слов паразитов: Калибровка уровня шума в помещении,\n сохраняйте тишину + Папка для сохранения на Google-диск + drive_folder_key а именно а не то diff --git a/app/src/main/res/xml/pref_general.xml b/app/src/main/res/xml/pref_general.xml index 1396ae20..c84da5c3 100644 --- a/app/src/main/res/xml/pref_general.xml +++ b/app/src/main/res/xml/pref_general.xml @@ -47,5 +47,12 @@ android:singleLine="true" android:title="@string/speech_speed" /> + + +