diff --git a/.idea/misc.xml b/.idea/misc.xml index 69d113f42b6501e3869200a85c41835667325f4f..75ced089ede07afcea1139e518741714ef0bf4aa 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -4,6 +4,46 @@ diff --git a/.idea/navEditor.xml b/.idea/navEditor.xml index 794fc6bfe9af57efa1890068bedc753ffba36c6d..0b1e61c79a574e9e5ae191d10dae09b4993117c0 100644 --- a/.idea/navEditor.xml +++ b/.idea/navEditor.xml @@ -3,6 +3,28 @@ diff --git a/app/build.gradle b/app/build.gradle index 8936ea7c57deb78f7cfcfae690dcc4a4f3dc65bc..0d8cee96ddcdf7cf5ffee4db6be6694ae4a75ca1 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -34,6 +34,10 @@ android { jvmTarget = JavaVersion.VERSION_1_8.toString() } buildToolsVersion = '29.0.2' + + dataBinding { + enabled = true + } } dependencies { @@ -82,6 +86,8 @@ dependencies { implementation "net.openid:appauth:0.7.1" implementation "com.journeyapps:zxing-android-embedded:$zxing_version" + + implementation "com.google.android.material:material:1.1.0" } repositories { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 27bb08dffc69a670dbdf13a916f2f5c3fed4327d..ee3cb7c7d2a65c4eb38a486f1b5a6f6ac5af4063 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -18,7 +18,8 @@ tools:ignore="GoogleAppIndexingWarning"> + android:exported="true" + android:theme="@style/AppTheme.NoActionBar"> @@ -35,6 +36,12 @@ android:launchMode="singleTask" android:theme="@style/AppTheme.NoActionBar"> + + + + + diff --git a/app/src/main/java/jp/atled/agileworks/AwApp.kt b/app/src/main/java/jp/atled/agileworks/AwApp.kt index ac154a4b91b290344ece4a34f3bd235ee2333869..7e3fdb14e9b621528eb5c21de08aa1c82bb47614 100644 --- a/app/src/main/java/jp/atled/agileworks/AwApp.kt +++ b/app/src/main/java/jp/atled/agileworks/AwApp.kt @@ -45,6 +45,7 @@ class AwApp : Application() { const val APP_AUTH_STATE = "appAuthState" const val APP_SERVER_DOMAIN = "appServerDomain" const val APP_SERVER_CONTEXT = "appServerContext" + const val APP_SYSTEM_NAME = "appSystemName" const val CLIENT_ID = "androidapp.agileworks.atled.jp" const val REDIRECT_URI = "awapp://auth_callback" const val AUTHORIZATION_SERVER = "oauth2" @@ -58,10 +59,13 @@ class AwApp : Application() { const val MISC_NEXT_DOWNLOAD_NOTIFICATION_ID = "nextDownloadNotificationId" const val WIDGET_PREFERENCES = "widgetPreferences" const val WIDGET_UPDATE_FLG = "widgetUpdateFlg" + const val SERVER_PREFERENCES = "serverPreferences" + const val SERVER_LIST = "serverList" + const val SERVER_ID = "serverId" - fun Baseurl() : String { - return "https://${LoginRepository().loadServerUrl()}/${LoginRepository().loadServerContext()}/" + fun Baseurl(serverNumber: Int? = null) : String { + return "https://${LoginRepository(serverNumber).loadServerUrl()}/${LoginRepository(serverNumber).loadServerContext()}/" } } } \ No newline at end of file diff --git a/app/src/main/java/jp/atled/agileworks/model/ApiSessionResponse.kt b/app/src/main/java/jp/atled/agileworks/model/ApiSessionResponse.kt index d75f5e7b7c1b64ad981a51408b097a9cbda23185..38866a6e28083b6eddac8598d700d4a700ee972d 100644 --- a/app/src/main/java/jp/atled/agileworks/model/ApiSessionResponse.kt +++ b/app/src/main/java/jp/atled/agileworks/model/ApiSessionResponse.kt @@ -7,7 +7,8 @@ data class SessionResponse( var user: ResponseSessionUser, var unit: List, var role: List, - var session_id: String + var session_id: String, + var system_name: String = "" ) @JsonClass(generateAdapter = true) diff --git a/app/src/main/java/jp/atled/agileworks/model/AuthStateRepository.kt b/app/src/main/java/jp/atled/agileworks/model/AuthStateRepository.kt index 07318428006c04f1f978cba94cd4f09e151fda9b..97a560daebc563edfb3dc13f6efd5f32e28f3d07 100644 --- a/app/src/main/java/jp/atled/agileworks/model/AuthStateRepository.kt +++ b/app/src/main/java/jp/atled/agileworks/model/AuthStateRepository.kt @@ -1,31 +1,47 @@ package jp.atled.agileworks.model import android.content.Context +import android.content.SharedPreferences import jp.atled.agileworks.AwApp import jp.atled.agileworks.widget.WidgetUpdate import net.openid.appauth.AuthState -class AuthStateRepository { +class AuthStateRepository(_serverNumber: Int? = null) { + val serverNumber: Int? + init { + serverNumber = _serverNumber + } + + private fun getSharedPreference(serverNumber: Int?): SharedPreferences { + var preferences: String = AwApp.APP_AUTH_PREFERENCES + if (serverNumber != null) { + preferences += serverNumber.toString() + }else { + preferences += ServerRepository().loadServer().toString() + } + return AwApp.instance.applicationContext.getSharedPreferences(preferences, Context.MODE_PRIVATE) + } + + private val prefs: SharedPreferences + get() = getSharedPreference(serverNumber) + fun loadAuthState(): AuthState { - val prefs = AwApp.instance.applicationContext.getSharedPreferences(AwApp.APP_AUTH_PREFERENCES, Context.MODE_PRIVATE) val data = decryptString(prefs.getString(AwApp.APP_AUTH_STATE, null)) ?: "{}" return AuthState.jsonDeserialize(data) } fun setAuthState(authState: AuthState) { authState.createTokenRefreshRequest() - AwApp.instance.applicationContext.getSharedPreferences(AwApp.APP_AUTH_PREFERENCES, Context.MODE_PRIVATE) - .edit() - .putString(AwApp.APP_AUTH_STATE, encryptString(authState.jsonSerializeString())) - .apply() + prefs.edit() + .putString(AwApp.APP_AUTH_STATE, encryptString(authState.jsonSerializeString())) + .apply() WidgetUpdate.update() } fun clear() { - AwApp.instance.applicationContext.getSharedPreferences(AwApp.APP_AUTH_PREFERENCES, Context.MODE_PRIVATE) - .edit() - .remove(AwApp.APP_AUTH_STATE) - .apply() + prefs.edit() + .remove(AwApp.APP_AUTH_STATE) + .apply() WidgetUpdate.update() } } \ No newline at end of file diff --git a/app/src/main/java/jp/atled/agileworks/model/CertRepository.kt b/app/src/main/java/jp/atled/agileworks/model/CertRepository.kt index f49d39eccbb223f88e0279d5fb1ae0fa82df0211..3bf582e6d2d8a0b9f37f7dd6750922a08961e506 100644 --- a/app/src/main/java/jp/atled/agileworks/model/CertRepository.kt +++ b/app/src/main/java/jp/atled/agileworks/model/CertRepository.kt @@ -87,8 +87,15 @@ object CertRepository { } } - private val prefs: SharedPreferences - get() = AwApp.instance.getSharedPreferences(AwApp.CERT_PREFERENCES, Context.MODE_PRIVATE) + private fun getSharedPreference(serverNumber: Int?): SharedPreferences { + var preferences: String = AwApp.CERT_PREFERENCES + if (serverNumber != null) { + preferences += serverNumber.toString() + }else { + preferences += ServerRepository().loadServer().toString() + } + return AwApp.instance.applicationContext.getSharedPreferences(preferences, Context.MODE_PRIVATE) + } // KeyChain からの読み込みは非同期となり、都度読み込みだと面倒になるためキャッシュしておく private val clientCertHolder = AsyncInitValueHolder() @@ -102,14 +109,16 @@ object CertRepository { clientCertHolder.initialize(this::loadClientCertFromPrefs, onFinished) } - private fun loadClientCertAlias() = prefs.getString(AwApp.CERT_CLIENT_CERT_ALIAS, null) - private fun saveClientCertAlias(alias: String) { - prefs.edit() + private fun loadClientCertAlias(serverNumber: Int? = null): String?{ + return getSharedPreference(serverNumber).getString(AwApp.CERT_CLIENT_CERT_ALIAS, null) + } + private fun saveClientCertAlias(serverNumber: Int? = null, alias: String) { + getSharedPreference(serverNumber).edit() .putString(AwApp.CERT_CLIENT_CERT_ALIAS, alias) .apply() } - private fun clearClientCertAlias() { - prefs.edit() + private fun clearClientCertAlias(serverNumber: Int? = null) { + getSharedPreference(serverNumber).edit() .remove(AwApp.CERT_CLIENT_CERT_ALIAS) .apply() } @@ -163,7 +172,7 @@ object CertRepository { if (cert == null) { clearClientCertAlias() } else { - saveClientCertAlias(cert.alias) + saveClientCertAlias(null, cert.alias) } onResult(cert) } diff --git a/app/src/main/java/jp/atled/agileworks/model/DeviceInfoRepository.kt b/app/src/main/java/jp/atled/agileworks/model/DeviceInfoRepository.kt index e28f020fec33621e5c8b9a18810543b6235be6b1..bece3c3db009eca75dd506b09e9caa2827dca131 100644 --- a/app/src/main/java/jp/atled/agileworks/model/DeviceInfoRepository.kt +++ b/app/src/main/java/jp/atled/agileworks/model/DeviceInfoRepository.kt @@ -2,21 +2,45 @@ package jp.atled.agileworks.model import android.app.Activity import android.content.Context +import android.content.SharedPreferences import android.os.Build import jp.atled.agileworks.AwApp import jp.atled.agileworks.model.api.ApiCallbackCommon import jp.atled.agileworks.model.api.ApiClient -class DeviceInfoRepository { +class DeviceInfoRepository(_serverNumber: Int? = null) { + val serverNumber: Int? + init { + serverNumber = _serverNumber + } + private fun getSharedPreference(serverNumber: Int?): SharedPreferences { + var preferences: String = AwApp.DEVICE_INFO_PREFERENCES + if (serverNumber != null) { + preferences += serverNumber.toString() + }else { + preferences += ServerRepository().loadServer().toString() + } + return AwApp.instance.applicationContext.getSharedPreferences(preferences, Context.MODE_PRIVATE) + } + + private val prefs: SharedPreferences + get() = getSharedPreference(serverNumber) + fun loadDeviceId(): Int? { - val prefs = AwApp.instance.applicationContext.getSharedPreferences(AwApp.DEVICE_INFO_PREFERENCES, Context.MODE_PRIVATE) val deviceId = prefs.getInt(AwApp.DEVICE_ID, -1) return if (deviceId >= 0) { deviceId } else { null } } + // 旧情報引継ぎ用 + fun setDeviceInfo(deviceId: Int, fcmToken: String) { + prefs.edit() + .putInt(AwApp.DEVICE_ID, deviceId) + .putString(AwApp.DEVICE_FCM_TOKEN, fcmToken) + .apply() + } + // 何らかの理由で FCM Token が登録したものとずれていないかチェックするために FCM のサービスに記録されているものとの比較も行う fun loadOrCreateDeviceId(activity: Activity, fcmToken: String, onResult: (isSuccess: Boolean, deviceId: Int?) -> Unit) { - val prefs = AwApp.instance.applicationContext.getSharedPreferences(AwApp.DEVICE_INFO_PREFERENCES, Context.MODE_PRIVATE) val deviceId = prefs.getInt(AwApp.DEVICE_ID, -1) val loadedFcmToken = prefs.getString(AwApp.DEVICE_FCM_TOKEN, null) val onCreate: (Boolean, DeviceInfo?) -> Unit = { _, deviceInfo -> @@ -65,7 +89,6 @@ class DeviceInfoRepository { } fun removeDeviceInfo() { - val prefs = AwApp.instance.applicationContext.getSharedPreferences(AwApp.DEVICE_INFO_PREFERENCES, Context.MODE_PRIVATE) val deviceId = prefs.getInt(AwApp.DEVICE_ID, -1) // ログアウト時デバイス情報削除 if (deviceId >= 0) { diff --git a/app/src/main/java/jp/atled/agileworks/model/LicenseRepository.kt b/app/src/main/java/jp/atled/agileworks/model/LicenseRepository.kt index b84b0e76bc7d66d388e16947190fe91d5e85db05..22257129c840f2e3250dd71ebf6435f863ba00eb 100644 --- a/app/src/main/java/jp/atled/agileworks/model/LicenseRepository.kt +++ b/app/src/main/java/jp/atled/agileworks/model/LicenseRepository.kt @@ -16,9 +16,9 @@ import jp.atled.agileworks.AwApp * * ライセンス既読情報は雑多設定格納用プリファレンス [AwApp.MISC_PREFERENCES] 内に格納される。 */ -object LicenseRepository { +class LicenseRepository() { private val prefs: SharedPreferences - get() = AwApp.instance.getSharedPreferences(AwApp.MISC_PREFERENCES, Context.MODE_PRIVATE) + get() = AwApp.instance.applicationContext.getSharedPreferences(AwApp.MISC_PREFERENCES, Context.MODE_PRIVATE) /** * 最後に同意された利用許諾書のバージョンを取得。許諾したことがなければ -1。 diff --git a/app/src/main/java/jp/atled/agileworks/model/LoginRepository.kt b/app/src/main/java/jp/atled/agileworks/model/LoginRepository.kt index a28158567aabc9de746b6b35c638b6f413d3ee99..a007ba4c04e8bf3c98ed68a5e934f91a7fc4387b 100644 --- a/app/src/main/java/jp/atled/agileworks/model/LoginRepository.kt +++ b/app/src/main/java/jp/atled/agileworks/model/LoginRepository.kt @@ -1,31 +1,59 @@ package jp.atled.agileworks.model import android.content.Context +import android.content.SharedPreferences import jp.atled.agileworks.AwApp import jp.atled.agileworks.model.api.ApiClient -class LoginRepository { +class LoginRepository(_serverNumber: Int? = null) { + val serverNumber: Int? + init { + serverNumber = _serverNumber + } + + private fun getSharedPreference(serverNumber: Int?): SharedPreferences { + var preferences: String = AwApp.APP_AUTH_PREFERENCES + if (serverNumber != null) { + preferences += serverNumber.toString() + }else { + preferences += ServerRepository().loadServer().toString() + } + return AwApp.instance.applicationContext.getSharedPreferences(preferences, Context.MODE_PRIVATE) + } + + private val prefs: SharedPreferences + get() = getSharedPreference(serverNumber) + private val TAG = "LoginRepository" fun loadServerUrl(): String { - val prefs = AwApp.instance.applicationContext.getSharedPreferences(AwApp.APP_AUTH_PREFERENCES, Context.MODE_PRIVATE) return prefs.getString(AwApp.APP_SERVER_DOMAIN, null)?.stripScheme().orEmpty() } fun setServerUrl(serverUrl: String) { - AwApp.instance.applicationContext.getSharedPreferences(AwApp.APP_AUTH_PREFERENCES, Context.MODE_PRIVATE) - .edit() - .putString(AwApp.APP_SERVER_DOMAIN, serverUrl) - .apply() + prefs.edit() + .putString(AwApp.APP_SERVER_DOMAIN, serverUrl) + .apply() ApiClient.reCreate() } fun loadServerContext(): String { - val prefs = AwApp.instance.applicationContext.getSharedPreferences(AwApp.APP_AUTH_PREFERENCES, Context.MODE_PRIVATE) return prefs.getString(AwApp.APP_SERVER_CONTEXT, "").orEmpty() } fun setServerContext(serverContext: String) { - AwApp.instance.applicationContext.getSharedPreferences(AwApp.APP_AUTH_PREFERENCES, Context.MODE_PRIVATE) - .edit() - .putString(AwApp.APP_SERVER_CONTEXT, serverContext) - .apply() + prefs.edit() + .putString(AwApp.APP_SERVER_CONTEXT, serverContext) + .apply() + ApiClient.reCreate() + } + fun loadSystemName(): String { + val systemName = prefs.getString(AwApp.APP_SYSTEM_NAME, "") + if (systemName!!.isEmpty()) { + return loadServerUrl() + } + return systemName + } + fun setSystemName(name: String) { + prefs.edit() + .putString(AwApp.APP_SYSTEM_NAME, name) + .apply() ApiClient.reCreate() } // 以前のバージョンでは "https://" が付いていたので取り除く。 diff --git a/app/src/main/java/jp/atled/agileworks/model/NotificationRepository.kt b/app/src/main/java/jp/atled/agileworks/model/NotificationRepository.kt index 9dfd878841209ab81e5229d699adefd8dba800c5..c8890acaea74161236208121a95042679402c4ad 100644 --- a/app/src/main/java/jp/atled/agileworks/model/NotificationRepository.kt +++ b/app/src/main/java/jp/atled/agileworks/model/NotificationRepository.kt @@ -2,6 +2,7 @@ package jp.atled.agileworks.model import android.app.Activity import android.content.Context +import android.content.SharedPreferences import android.util.Log import jp.atled.agileworks.AwApp import jp.atled.agileworks.model.api.ApiClient @@ -9,7 +10,25 @@ import jp.atled.agileworks.model.api.ApiClient /** * 通知全般を扱うリポジトリ */ -class NotificationRepository { +class NotificationRepository(_serverNumber: Int? = null) { + val serverNumber: Int? + init { + serverNumber = _serverNumber + } + + private fun getSharedPreference(serverNumber: Int?): SharedPreferences { + var preferences: String = AwApp.MISC_PREFERENCES + if (serverNumber != null) { + preferences += serverNumber.toString() + }else { + preferences += ServerRepository().loadServer().toString() + } + return AwApp.instance.applicationContext.getSharedPreferences(preferences, Context.MODE_PRIVATE) + } + + private val prefs: SharedPreferences + get() = getSharedPreference(serverNumber) + fun setToken(activity: Activity?, token: String) { Log.d("AgileWorks", "firebase token set : $token") DeviceInfoRepository().updateFcmToken(activity, token) { success, _ -> @@ -19,12 +38,22 @@ class NotificationRepository { fun clearToken(onResult: (Boolean) -> Unit) { Log.d("AgileWorks", "firebase token clean") - ApiClient.reCreateLogout() + ApiClient.reCreateLogout(serverNumber) LogoutRepository.getInstance().getLogout { + /* FcmRepository().removeFcmToken { Log.d("AgileWorks", "firebase token clean -> ${successOrFailured(it)}") onResult(it) } + */ + // 全サーバログアウト状態で FcmToken の削除 + val serverList = ServerRepository().loadServerList() + if (serverList.isEmpty()) { + FcmRepository().removeFcmToken { + Log.d("AgileWorks", "firebase token clean -> ${successOrFailured(it)}") + } + } + onResult(it) } } @@ -34,7 +63,6 @@ class NotificationRepository { * ファイルダウンロード通知に利用する ID を取得する。呼び出す毎に異なる値が返る。 */ fun nextDownloadNotificationId(): Int { - val prefs = AwApp.instance.getSharedPreferences(AwApp.MISC_PREFERENCES, Context.MODE_PRIVATE) val notificationId = prefs.getInt(AwApp.MISC_NEXT_DOWNLOAD_NOTIFICATION_ID, 0) val nextNotificationId = if (notificationId == Int.MAX_VALUE) { 0 } else { notificationId + 1 } prefs.edit() diff --git a/app/src/main/java/jp/atled/agileworks/model/OldSharedPreferenceRepository.kt b/app/src/main/java/jp/atled/agileworks/model/OldSharedPreferenceRepository.kt new file mode 100644 index 0000000000000000000000000000000000000000..996db1d24d6c01065902697e8f77787c3f74f200 --- /dev/null +++ b/app/src/main/java/jp/atled/agileworks/model/OldSharedPreferenceRepository.kt @@ -0,0 +1,59 @@ +package jp.atled.agileworks.model + +import android.content.Context +import jp.atled.agileworks.AwApp +import jp.atled.agileworks.widget.WidgetUpdate +import net.openid.appauth.AuthState + +class OldSharedPreferenceRepository { + fun loadAuthState(): AuthState { + val prefs = AwApp.instance.applicationContext.getSharedPreferences(AwApp.APP_AUTH_PREFERENCES, Context.MODE_PRIVATE) + val data = decryptString(prefs.getString(AwApp.APP_AUTH_STATE, null)) ?: "{}" + return AuthState.jsonDeserialize(data) + } + fun loadServerUrl(): String { + val prefs = AwApp.instance.applicationContext.getSharedPreferences(AwApp.APP_AUTH_PREFERENCES, Context.MODE_PRIVATE) + return prefs.getString(AwApp.APP_SERVER_DOMAIN, null)?.stripScheme().orEmpty() + } + fun loadServerContext(): String { + val prefs = AwApp.instance.applicationContext.getSharedPreferences(AwApp.APP_AUTH_PREFERENCES, Context.MODE_PRIVATE) + return prefs.getString(AwApp.APP_SERVER_CONTEXT, "").orEmpty() + } + + fun loadDeviceId(): Int { + val prefs = AwApp.instance.applicationContext.getSharedPreferences(AwApp.DEVICE_INFO_PREFERENCES, Context.MODE_PRIVATE) + return prefs.getInt(AwApp.DEVICE_ID, -1) + } + + fun loadDeviceFcmToken(): String? { + val prefs = AwApp.instance.applicationContext.getSharedPreferences(AwApp.DEVICE_INFO_PREFERENCES, Context.MODE_PRIVATE) + return prefs.getString(AwApp.DEVICE_FCM_TOKEN, null) + + } + + fun loadSessionId(): String { + val cookiePref = AwApp.instance.applicationContext.getSharedPreferences("cookie", Context.MODE_PRIVATE) + return cookiePref.getString("sessionId", "") ?: "" + } + fun loadClientCertAlias(): String { + val certPref = AwApp.instance.getSharedPreferences(AwApp.CERT_PREFERENCES, Context.MODE_PRIVATE) + return certPref.getString(AwApp.CERT_CLIENT_CERT_ALIAS, "") ?: "" + } + fun clear() { + AwApp.instance.applicationContext.getSharedPreferences(AwApp.APP_AUTH_PREFERENCES, Context.MODE_PRIVATE) + .edit() + .remove(AwApp.APP_AUTH_STATE) + .apply() + WidgetUpdate.update() + } + + + + // 以前のバージョンでは "https://" が付いていたので取り除く。 + private fun String.stripScheme(): String = OldSharedPreferenceRepository.SCHEME_PATTERN.replaceFirst(this, "") + + companion object { + private val SCHEME_PATTERN = Regex("^https?://") + } + +} \ No newline at end of file diff --git a/app/src/main/java/jp/atled/agileworks/model/ServerRepository.kt b/app/src/main/java/jp/atled/agileworks/model/ServerRepository.kt new file mode 100644 index 0000000000000000000000000000000000000000..57a6dd378a053403fe64493cadb5870516fb8ae8 --- /dev/null +++ b/app/src/main/java/jp/atled/agileworks/model/ServerRepository.kt @@ -0,0 +1,90 @@ +package jp.atled.agileworks.model + +import android.content.Context +import android.content.SharedPreferences +import jp.atled.agileworks.AwApp +import jp.atled.agileworks.model.api.ApiClient +import org.json.JSONArray + +class ServerRepository() { + private val prefs: SharedPreferences + get() = AwApp.instance.applicationContext.getSharedPreferences(AwApp.SERVER_PREFERENCES, Context.MODE_PRIVATE) + + private val serverCount = 5 + + fun setServerList(serverList: ArrayList) { + val jsonArray = JSONArray(serverList) + prefs.edit() + .putString(AwApp.SERVER_LIST, jsonArray.toString()) + .apply() + } + + fun loadServerList(): ArrayList { + val serverList = prefs.getString(AwApp.SERVER_LIST, "[]") + val jsonArray = JSONArray(serverList); + val arrayList : ArrayList = ArrayList() + + for (i in 0 until jsonArray.length()) { + arrayList.add(jsonArray.get(i) as Int) + } + return arrayList + } + + fun setServer(serverNumber: Int) { + prefs.edit() + .putInt(AwApp.SERVER_ID, serverNumber) + .apply() + } + + fun loadServer(): Int { + return prefs.getInt(AwApp.SERVER_ID, -1) + } + + fun removeServerList() { + prefs.edit() + .remove(AwApp.SERVER_LIST) + .apply() + } + + fun removeServer() { + var serverList = loadServerList() + serverList.removeAt(0) + setServerList(serverList) + } + + //サーバー接続先を保存できる識別番号を探す + fun serchEmptyServerData(): Int? { + var serverList = loadServerList() + + if (serverList.isNullOrEmpty()) { + return serverList.size + } + + for (num in 0 until serverCount){ + if (!serverList.contains(num)) { + return num + } + } + return null + } + + //サーバー追加 + fun addServerList() { + var serverList = loadServerList() + val serverNumber = serchEmptyServerData() + serverList.add(0, serverNumber!!) + setServerList(serverList) + } + + //サーバー並び替え + fun changeServerList(firstServer: Int) { + var serverList = loadServerList() + if (serverList.contains(firstServer)) { + //要素を削除してから先頭に追加する + serverList.remove(firstServer) + serverList.add(0, firstServer) + setServerList(serverList) + } + } + +} diff --git a/app/src/main/java/jp/atled/agileworks/model/SessionRepository.kt b/app/src/main/java/jp/atled/agileworks/model/SessionRepository.kt index 59517d666f674c7f65516ca9ab749e3882fa0d1a..61092c17729caea6f07cdddf3f137eda5f97dffb 100644 --- a/app/src/main/java/jp/atled/agileworks/model/SessionRepository.kt +++ b/app/src/main/java/jp/atled/agileworks/model/SessionRepository.kt @@ -6,7 +6,8 @@ import jp.atled.agileworks.model.api.ApiClient class SessionRepository(private val activity: Activity?) { fun getSession(onResult: (isSuccess: Boolean, response: SessionResponse?) -> Unit) { - ApiClient.instance.getSession().enqueue(ApiCallbackCommon(activity, onResult)) + val instance = ApiClient.instance(null) + instance.getSession().enqueue(ApiCallbackCommon(activity, onResult)) } companion object { diff --git a/app/src/main/java/jp/atled/agileworks/model/WidgetRepository.kt b/app/src/main/java/jp/atled/agileworks/model/WidgetRepository.kt new file mode 100644 index 0000000000000000000000000000000000000000..1bcd2a3d4c03135702d0322aa715d91c47212e83 --- /dev/null +++ b/app/src/main/java/jp/atled/agileworks/model/WidgetRepository.kt @@ -0,0 +1,28 @@ +package jp.atled.agileworks.model + +import android.content.Context +import androidx.core.content.edit +import jp.atled.agileworks.AwApp + +class WidgetRepository { + private val PREF_PREFIX_KEY = "appwidget_" + + internal fun saveWidgetLayoutIdPref( + appWidgetId: Int, + serverNumber: Int + ) { + AwApp.instance.applicationContext.getSharedPreferences(AwApp.WIDGET_PREFERENCES, Context.MODE_PRIVATE).edit { + putInt(PREF_PREFIX_KEY + appWidgetId, serverNumber) + } + } + + fun loadWidgetLayoutIdPref(appWidgetId: Int): Int = + AwApp.instance.applicationContext.getSharedPreferences(AwApp.WIDGET_PREFERENCES, Context.MODE_PRIVATE) + .getInt(PREF_PREFIX_KEY + appWidgetId, 0) + + fun deleteWidgetLayoutIdPref(appWidgetId: Int) { + AwApp.instance.applicationContext.getSharedPreferences(AwApp.WIDGET_PREFERENCES, Context.MODE_PRIVATE).edit { + remove(PREF_PREFIX_KEY + appWidgetId) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/jp/atled/agileworks/model/api/ApiClient.kt b/app/src/main/java/jp/atled/agileworks/model/api/ApiClient.kt index b4ecb96856f08011e9582d9af65d890298b67013..068b008114c4caf13d925d023b40642eab5dacf3 100644 --- a/app/src/main/java/jp/atled/agileworks/model/api/ApiClient.kt +++ b/app/src/main/java/jp/atled/agileworks/model/api/ApiClient.kt @@ -3,10 +3,7 @@ package jp.atled.agileworks.model.api import android.content.Context import com.squareup.moshi.Moshi import jp.atled.agileworks.AwApp -import jp.atled.agileworks.model.AuthStateRepository -import jp.atled.agileworks.model.CertRepository -import jp.atled.agileworks.model.DeviceInfoRepository -import jp.atled.agileworks.model.RefreshTokenRepository +import jp.atled.agileworks.model.* import jp.atled.agileworks.view.utils.Constants.Companion.DEBUG import jp.atled.agileworks.view.utils.Constants.Companion.REQUEST_TIMEOUT_DURATION import net.openid.appauth.TokenResponse @@ -16,25 +13,30 @@ import retrofit2.Retrofit import retrofit2.converter.moshi.MoshiConverterFactory import java.util.concurrent.TimeUnit + object ApiClient { - var instance: ApiService = createRetrofitInstance(false) + var instance: ApiService = createRetrofitInstance(isLogout = false) + fun instance(serverNumber: Int?) : ApiService{ + instance = createRetrofitInstance(serverNumber,false) + return instance + } fun reCreate() { - instance = createRetrofitInstance(false) + instance = createRetrofitInstance(isLogout = false) } - var instanceLogout: ApiService = createRetrofitInstance(true) - fun reCreateLogout() { - instanceLogout = createRetrofitInstance(true) + var instanceLogout: ApiService = createRetrofitInstance(isLogout = true) + fun reCreateLogout(serverNumber: Int? = null) { + instanceLogout = createRetrofitInstance(serverNumber, isLogout = true) } - private fun createRetrofitInstance(isLogout: Boolean): ApiService { + private fun createRetrofitInstance(serverNumber: Int? = null, isLogout: Boolean): ApiService { return Retrofit.Builder().run { val moshi = Moshi.Builder() .add(com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory()) .build() - baseUrl(AwApp.Baseurl()) + baseUrl(AwApp.Baseurl(serverNumber)) addConverterFactory(MoshiConverterFactory.create(moshi)) - client(createRequestInterceptorClient(isLogout)) + client(createRequestInterceptorClient(isLogout, serverNumber)) build() }.create(ApiService::class.java) @@ -51,10 +53,11 @@ object ApiClient { } } - class BearerAuthenticationInterceptor() : Interceptor { + class BearerAuthenticationInterceptor(serverNumber: Int?) : Interceptor { + val serverNumber = serverNumber override fun intercept(chain: Interceptor.Chain): Response { - var authState = AuthStateRepository().loadAuthState() - val deviceId = DeviceInfoRepository().loadDeviceId() + var authState = AuthStateRepository(serverNumber).loadAuthState() + val deviceId = DeviceInfoRepository(serverNumber).loadDeviceId() val builder = chain.request().newBuilder() .header( "Authorization", @@ -135,7 +138,10 @@ object ApiClient { } } - private fun createRequestInterceptorClient(isLogout: Boolean): OkHttpClient { + private fun createRequestInterceptorClient(isLogout: Boolean, serverNumber: Int?): OkHttpClient { + val logging = HttpLoggingInterceptor() + logging.level = HttpLoggingInterceptor.Level.HEADERS + var interceptor = Interceptor { chain -> val original = chain.request() val requestBuilder = original.newBuilder() @@ -145,7 +151,8 @@ object ApiClient { if (isLogout) { // 保存しているセッションIDを取得 - val cookiePref = AwApp.instance.applicationContext.getSharedPreferences("cookie", Context.MODE_PRIVATE) + var preferences = "cookie" + ServerRepository().loadServer().toString() + val cookiePref = AwApp.instance.applicationContext.getSharedPreferences(preferences, Context.MODE_PRIVATE) val sessionId = cookiePref.getString("sessionId", "") ?: "" interceptor = Interceptor { chain -> val original = chain.request() @@ -161,10 +168,11 @@ object ApiClient { return if (DEBUG) { OkHttpClient.Builder() + .addInterceptor(logging) .addInterceptor(interceptor) .addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)) .addInterceptor(OfflineCheckInterceptor(AwApp.instance.applicationContext)) - .addInterceptor(BearerAuthenticationInterceptor()) + .addInterceptor(BearerAuthenticationInterceptor(serverNumber)) .authenticator(TokenAuthenticator()) .connectTimeout(REQUEST_TIMEOUT_DURATION.toLong(), TimeUnit.SECONDS) .readTimeout(REQUEST_TIMEOUT_DURATION.toLong(), TimeUnit.SECONDS) @@ -175,9 +183,10 @@ object ApiClient { .build() } else { OkHttpClient.Builder() + .addInterceptor(logging) .addInterceptor(interceptor) .addInterceptor(OfflineCheckInterceptor(AwApp.instance.applicationContext)) - .addInterceptor(BearerAuthenticationInterceptor()) + .addInterceptor(BearerAuthenticationInterceptor(serverNumber)) .authenticator(TokenAuthenticator()) .connectTimeout(REQUEST_TIMEOUT_DURATION.toLong(), TimeUnit.SECONDS) .readTimeout(REQUEST_TIMEOUT_DURATION.toLong(), TimeUnit.SECONDS) diff --git a/app/src/main/java/jp/atled/agileworks/view/ui/DirectOpenDocumentActivity.kt b/app/src/main/java/jp/atled/agileworks/view/ui/DirectOpenDocumentActivity.kt index d3584ec392a056feaf59f48e341fd78c95349450..837822514964fe6c28144df6c6e8952f08de6d0b 100644 --- a/app/src/main/java/jp/atled/agileworks/view/ui/DirectOpenDocumentActivity.kt +++ b/app/src/main/java/jp/atled/agileworks/view/ui/DirectOpenDocumentActivity.kt @@ -1,6 +1,8 @@ package jp.atled.agileworks.view.ui +import android.app.AlertDialog import android.content.Context +import android.content.DialogInterface import android.content.Intent import android.content.res.Configuration import android.os.Bundle @@ -16,16 +18,33 @@ import kotlinx.android.synthetic.main.activity_main.* import android.view.KeyEvent import android.view.View import android.widget.Button +import jp.atled.agileworks.model.LoginRepository +import jp.atled.agileworks.model.ServerRepository +import kotlinx.android.synthetic.main.activity_main.app_ver_label +import kotlinx.android.synthetic.main.activity_main.toolbar +import kotlinx.android.synthetic.main.fragment_login.* class DirectOpenDocumentActivity : BaseActivity(), View.OnClickListener { private val TAG = "DirectOpenDocumentActivity" private lateinit var directOpenControl: DirectOpenControl + var tapServer = 0 + var firstServer= 0 + override fun onCreate(savedInstanceState: Bundle?) { Log.d(TAG, "call onCreate, url = ${intent?.getStringExtra("url")}, title = ${intent?.getStringExtra("title")}") super.onCreate(savedInstanceState) + val serverList = ServerRepository().loadServerList() + firstServer = serverList.first() + tapServer = getTapServer(url()) + + //サーバー切り替え + if (firstServer != tapServer) { + ServerRepository().setServer(tapServer) + } + directOpenControl = DirectOpenControl(this) setContentView(R.layout.activity_direct_open_document) @@ -40,15 +59,62 @@ class DirectOpenDocumentActivity : BaseActivity(), View.OnClickListener { } //閉じるボタンが押された処理 override fun onClick(v: View?) { + if (firstServer != tapServer) { + createDialog().show() + } else { + closeTapped() + } + } + + private fun closeTapped(){ var event = KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK) dispatchKeyEvent(event) event = KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK) dispatchKeyEvent(event) } - private fun title() = intent.getStringExtra("title") ?: "" + private fun url() = intent.getStringExtra("url") ?: "" + + private fun getTapServer(url: String): Int { + val serverList = ServerRepository().loadServerList() + + for (server in serverList){ + val serverUrl = LoginRepository(server).loadServerUrl() + if (url.contains(serverUrl)) { + return server + } + } + return 0 + } + + private fun createDialog(): AlertDialog { + val context = this + val dialog = AlertDialog.Builder(context) + .setCancelable(false) + .setTitle(R.string.notification_confirmation_title) + .setMessage(R.string.notification_server_switch_message) + .setPositiveButton(R.string.notification_confirmation_dialog_positive, object : DialogInterface.OnClickListener { + override fun onClick(dialogInterface: DialogInterface, i: Int) { + Log.d(TAG, "alert dialog click positive") + ServerRepository().changeServerList(tapServer) + closeTapped() + MainActivity.start(context, null) + } + }) + .setNegativeButton(R.string.notification_confirmation_dialog_negative, object : DialogInterface.OnClickListener { + override fun onClick(dialogInterface: DialogInterface, i: Int) { + Log.d(TAG, "alert dialog click negative") + ServerRepository().setServer(firstServer) + closeTapped() + } + }) + .create() + + return dialog + } + private fun setupDrawerMenu() { DrawerMenu.setup(this, drawer_layout, navigation_drawer) app_ver_label.text = getString(R.string.app_ver_format, BuildConfig.VERSION_NAME) diff --git a/app/src/main/java/jp/atled/agileworks/view/ui/DrawerMenu.kt b/app/src/main/java/jp/atled/agileworks/view/ui/DrawerMenu.kt index a3f1e62fcefdf88fb9f1a41c24ce912f93ad7b58..60c53b5c987a4ca5580aef7a41530c348b551451 100644 --- a/app/src/main/java/jp/atled/agileworks/view/ui/DrawerMenu.kt +++ b/app/src/main/java/jp/atled/agileworks/view/ui/DrawerMenu.kt @@ -1,14 +1,18 @@ package jp.atled.agileworks.view.ui +import BottomSheetFragment import android.app.Activity import android.content.Intent +import android.view.View import android.widget.TextView import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity import androidx.drawerlayout.widget.DrawerLayout import com.google.android.gms.oss.licenses.OssLicensesMenuActivity +import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.navigation.NavigationView import jp.atled.agileworks.R +import jp.atled.agileworks.model.LoginRepository import jp.atled.agileworks.model.SessionRepository import jp.atled.agileworks.view.ui.license.License import jp.atled.agileworks.view.ui.login.LoginUtil @@ -44,6 +48,12 @@ class DrawerMenu { val intent = Intent(activity, OssLicensesMenuActivity::class.java) activity.startActivity(intent) } + R.id.drawer_server_switching -> { + + lateinit var bottomSheetFragment: BottomSheetFragment + bottomSheetFragment = BottomSheetFragment() + bottomSheetFragment.show(activity.supportFragmentManager, "BSDialogFragment") + } } //押したらナビゲーションドロワーを閉じる layout.closeDrawer(drawer) @@ -54,7 +64,12 @@ class DrawerMenu { private fun setupUserName(activity: Activity, drawer: NavigationView) { SessionRepository.getInstance(activity).getSession { _, response -> val userName = response?.user?.name.orEmpty() - drawer.getHeaderView(0).findViewById(R.id.userName).text = userName + var systemName = response?.system_name.orEmpty() + val header = drawer.getHeaderView(0) + LoginRepository().setSystemName(systemName) + systemName = LoginRepository().loadSystemName() + header.findViewById(R.id.userName).text = userName + header.findViewById(R.id.server_Name).text = systemName } } diff --git a/app/src/main/java/jp/atled/agileworks/view/ui/ServerSwitchingMenu.kt b/app/src/main/java/jp/atled/agileworks/view/ui/ServerSwitchingMenu.kt new file mode 100644 index 0000000000000000000000000000000000000000..17ff0b703bd675520b1cb9b3a57e08bb38c551d6 --- /dev/null +++ b/app/src/main/java/jp/atled/agileworks/view/ui/ServerSwitchingMenu.kt @@ -0,0 +1,154 @@ +import android.app.LauncherActivity +import android.content.Context +import android.os.Bundle +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.* +import androidx.databinding.DataBindingUtil +import com.google.android.material.bottomsheet.BottomSheetDialogFragment +import jp.atled.agileworks.AwApp +import jp.atled.agileworks.R +import jp.atled.agileworks.model.ApprovalInfo +import jp.atled.agileworks.model.LoginRepository +import jp.atled.agileworks.model.ServerRepository +import jp.atled.agileworks.model.api.ApiClient +import jp.atled.agileworks.view.ui.MainActivity +import jp.atled.agileworks.view.ui.login.LoginActivity +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch +import kotlinx.coroutines.runBlocking +import java.io.IOException + +data class ServerListData( + val serverName: String, + var approvalCount: String, + val imageId: Int +) + +class BottomSheetFragment : BottomSheetDialogFragment() { + private val TAG="ServerSwitchingMenu" + override fun getTheme(): Int { + return R.style.AppBottomSheetDialogTheme + } + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle?): View? { + var view: View = inflater.inflate(R.layout.fragment_server_switching,container,false) + + //サーバー一覧 + val listView = view.findViewById(R.id.serverListView) + val serverListData = getServerListData() + val customAdapter = CustomAdapter(listView.context, serverListData) + listView.adapter = customAdapter + + //承認待ち件数 + setApprovalCount(customAdapter) + + //サーバー切り替え + listView.setOnItemClickListener { _, _, position, _ -> + if (position != 0) { + val serverList = ServerRepository().loadServerList() + ServerRepository().setServer(serverList[position]) + ServerRepository().changeServerList(serverList[position]) + + MainActivity.start(this.requireActivity(), arguments) + } else { + this.dismiss() + } + } + + //接続先追加 + val addServerButton = view.findViewById