🔥 Drop support for API 19 (KitKat)
I'm fed up with all the extra effort for supporting an outdated Android version. Apologies for the few users that are now excluded, but I feel like it's just not worth the hassle.
This commit is contained in:
parent
8b89d81970
commit
c6e29c056b
@ -21,7 +21,7 @@ android {
|
||||
}
|
||||
defaultConfig {
|
||||
applicationId "ch.dissem.apps.${appName.toLowerCase()}"
|
||||
minSdkVersion 19
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 27
|
||||
versionCode 23
|
||||
versionName "1.0-rc1"
|
||||
|
@ -175,20 +175,7 @@
|
||||
|
||||
<!-- Receive Wi-Fi connection state changes -->
|
||||
<receiver
|
||||
android:name=".listener.WifiReceiver"
|
||||
android:enabled="@bool/is_pre_api_21">
|
||||
<intent-filter>
|
||||
<!-- This is bad for battery life, but needed on older devices to check
|
||||
if WiFi is available. Let's be honest, the whole app is bad for
|
||||
battery life. -->
|
||||
<action
|
||||
android:name="android.net.conn.CONNECTIVITY_CHANGE"
|
||||
tools:ignore="BatteryLife" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
<receiver
|
||||
android:name=".service.StartServiceReceiver"
|
||||
android:enabled="@bool/is_post_api_21">
|
||||
android:name=".service.StartServiceReceiver">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||
</intent-filter>
|
||||
|
@ -4,7 +4,6 @@ import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.NavUtils
|
||||
import android.view.MenuItem
|
||||
import ch.dissem.bitmessage.entity.Conversation
|
||||
import ch.dissem.bitmessage.entity.Plaintext
|
||||
|
||||
|
||||
|
@ -18,8 +18,6 @@ package ch.dissem.apps.abit
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.*
|
||||
import android.os.Build
|
||||
import android.os.Build.VERSION_CODES.LOLLIPOP
|
||||
import android.os.Bundle
|
||||
import android.os.IBinder
|
||||
import android.support.v4.app.Fragment
|
||||
@ -264,7 +262,7 @@ class SettingsFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedP
|
||||
private fun connectivityChangeListener() =
|
||||
OnPreferenceChangeListener { _, _ ->
|
||||
context?.let { ctx ->
|
||||
if (Build.VERSION.SDK_INT >= LOLLIPOP && Preferences.isFullNodeActive(ctx)) {
|
||||
if (Preferences.isFullNodeActive(ctx)) {
|
||||
NetworkUtils.scheduleNodeStart(ctx)
|
||||
}
|
||||
}
|
||||
|
@ -149,7 +149,7 @@ class ConversationAdapter internal constructor(
|
||||
linksClickable = true
|
||||
setTextIsSelectable(true)
|
||||
}
|
||||
val labelAdapter = LabelAdapter(itemView.context, emptySet<Label>())
|
||||
val labelAdapter = LabelAdapter(itemView.context, emptySet())
|
||||
val labels = itemView.findViewById<RecyclerView>(R.id.labels)!!.apply {
|
||||
adapter = labelAdapter
|
||||
layoutManager = GridLayoutManager(itemView.context, 2)
|
||||
|
@ -2,7 +2,6 @@ package ch.dissem.apps.abit.adapter
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.ColorStateList
|
||||
import android.os.Build
|
||||
import android.support.annotation.ColorInt
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import android.view.LayoutInflater
|
||||
@ -15,7 +14,6 @@ import ch.dissem.apps.abit.util.getIcon
|
||||
import ch.dissem.apps.abit.util.getText
|
||||
import ch.dissem.bitmessage.entity.valueobject.Label
|
||||
import com.mikepenz.iconics.view.IconicsImageView
|
||||
import org.jetbrains.anko.backgroundColor
|
||||
|
||||
class LabelAdapter internal constructor(private val ctx: Context, labels: Collection<Label>) :
|
||||
RecyclerView.Adapter<LabelAdapter.ViewHolder>() {
|
||||
@ -50,11 +48,7 @@ class LabelAdapter internal constructor(private val ctx: Context, labels: Collec
|
||||
var label = itemView.findViewById<TextView>(R.id.label)!!
|
||||
|
||||
fun setBackground(@ColorInt color: Int) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
itemView.backgroundTintList = ColorStateList.valueOf(color)
|
||||
} else {
|
||||
itemView.backgroundColor = color
|
||||
}
|
||||
itemView.backgroundTintList = ColorStateList.valueOf(color)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,6 @@
|
||||
package ch.dissem.apps.abit.dialog
|
||||
|
||||
import android.app.Activity
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import ch.dissem.apps.abit.R
|
||||
import ch.dissem.apps.abit.util.NetworkUtils
|
||||
@ -37,9 +36,7 @@ class FullNodeDialogActivity : Activity() {
|
||||
finish()
|
||||
}
|
||||
dismiss.setOnClickListener {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
NetworkUtils.scheduleNodeStart(applicationContext)
|
||||
}
|
||||
NetworkUtils.scheduleNodeStart(applicationContext)
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 Christian Basler
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package ch.dissem.apps.abit.listener
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import ch.dissem.apps.abit.service.Singleton
|
||||
import ch.dissem.apps.abit.util.NetworkUtils
|
||||
import ch.dissem.apps.abit.util.Preferences
|
||||
import org.jetbrains.anko.connectivityManager
|
||||
|
||||
class WifiReceiver : BroadcastReceiver() {
|
||||
override fun onReceive(ctx: Context, intent: Intent) {
|
||||
if ("android.net.conn.CONNECTIVITY_CHANGE" == intent.action) {
|
||||
val bmc = Singleton.getBitmessageContext(ctx)
|
||||
if (Preferences.isFullNodeActive(ctx) && !bmc.isRunning() && !(Preferences.isWifiOnly(ctx) && ctx.connectivityManager.isActiveNetworkMetered)) {
|
||||
NetworkUtils.doStartBitmessageService(ctx)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -22,7 +22,6 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.net.ConnectivityManager
|
||||
import android.os.BatteryManager
|
||||
import android.os.Handler
|
||||
import ch.dissem.apps.abit.notification.NetworkNotification
|
||||
import ch.dissem.apps.abit.notification.NetworkNotification.Companion.NETWORK_NOTIFICATION_ID
|
||||
|
@ -14,7 +14,6 @@ import ch.dissem.apps.abit.util.Preferences
|
||||
*
|
||||
* And stops it when the preconditions for the job (unmetered network) aren't met anymore.
|
||||
*/
|
||||
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
class StartupNodeOnWifiService : JobService() {
|
||||
override fun onStartJob(params: JobParameters?): Boolean {
|
||||
val bmc = Singleton.getBitmessageContext(this)
|
||||
|
@ -24,6 +24,7 @@ import ch.dissem.apps.abit.service.Singleton
|
||||
import ch.dissem.apps.abit.synchronization.Authenticator.Companion.ACCOUNT_POW
|
||||
import ch.dissem.apps.abit.synchronization.Authenticator.Companion.ACCOUNT_SYNC
|
||||
import ch.dissem.apps.abit.synchronization.StubProvider.Companion.AUTHORITY
|
||||
import ch.dissem.apps.abit.util.NetworkUtils
|
||||
import ch.dissem.apps.abit.util.Preferences
|
||||
import ch.dissem.bitmessage.exception.DecryptionFailedException
|
||||
import ch.dissem.bitmessage.extensions.CryptoCustomMessage
|
||||
@ -43,11 +44,11 @@ class SyncAdapter(context: Context, autoInitialize: Boolean) : AbstractThreadedS
|
||||
private val bmc = Singleton.getBitmessageContext(context)
|
||||
|
||||
override fun onPerformSync(
|
||||
account: Account,
|
||||
extras: Bundle,
|
||||
authority: String,
|
||||
provider: ContentProviderClient,
|
||||
syncResult: SyncResult
|
||||
account: Account,
|
||||
extras: Bundle,
|
||||
authority: String,
|
||||
provider: ContentProviderClient,
|
||||
syncResult: SyncResult
|
||||
) {
|
||||
try {
|
||||
if (account == ACCOUNT_SYNC) {
|
||||
@ -75,16 +76,15 @@ class SyncAdapter(context: Context, autoInitialize: Boolean) : AbstractThreadedS
|
||||
}
|
||||
val trustedNode = Preferences.getTrustedNode(context)
|
||||
if (trustedNode == null) {
|
||||
LOG.info("Trusted node not available, disabling synchronization")
|
||||
stopSync(context)
|
||||
NetworkUtils.scheduleNodeStart(context)
|
||||
return
|
||||
}
|
||||
LOG.info("Synchronization started")
|
||||
bmc.synchronize(
|
||||
trustedNode,
|
||||
Preferences.getTrustedNodePort(context),
|
||||
Preferences.getTimeoutInSeconds(context),
|
||||
true
|
||||
trustedNode,
|
||||
Preferences.getTrustedNodePort(context),
|
||||
Preferences.getTimeoutInSeconds(context),
|
||||
true
|
||||
)
|
||||
LOG.info("Synchronization finished")
|
||||
}
|
||||
@ -104,7 +104,8 @@ class SyncAdapter(context: Context, autoInitialize: Boolean) : AbstractThreadedS
|
||||
// If the Bitmessage context acts as a full node, synchronization isn't necessary
|
||||
LOG.info("Looking for completed POW")
|
||||
|
||||
val privateKey = identity.privateKey?.privateEncryptionKey ?: throw IllegalStateException("Identity without private key")
|
||||
val privateKey =
|
||||
identity.privateKey?.privateEncryptionKey ?: throw IllegalStateException("Identity without private key")
|
||||
val signingKey = cryptography().createPublicKey(identity.publicDecryptionKey)
|
||||
val reader = ProofOfWorkRequest.Reader(identity)
|
||||
val powRepo = Singleton.getProofOfWorkRepository(context)
|
||||
@ -113,12 +114,13 @@ class SyncAdapter(context: Context, autoInitialize: Boolean) : AbstractThreadedS
|
||||
val (objectMessage, nonceTrialsPerByte, extraBytes) = powRepo.getItem(initialHash)
|
||||
val target = cryptography().getProofOfWorkTarget(objectMessage, nonceTrialsPerByte, extraBytes)
|
||||
val cryptoMsg = CryptoCustomMessage(
|
||||
ProofOfWorkRequest(identity, initialHash, CALCULATE, target))
|
||||
ProofOfWorkRequest(identity, initialHash, CALCULATE, target)
|
||||
)
|
||||
cryptoMsg.signAndEncrypt(identity, signingKey)
|
||||
val response = bmc.send(
|
||||
trustedNode,
|
||||
Preferences.getTrustedNodePort(context),
|
||||
cryptoMsg
|
||||
trustedNode,
|
||||
Preferences.getTrustedNodePort(context),
|
||||
cryptoMsg
|
||||
)
|
||||
if (response.isError) {
|
||||
LOG.error("Server responded with error: ${String(response.getData())}")
|
||||
|
@ -17,8 +17,6 @@
|
||||
package ch.dissem.apps.abit.util
|
||||
|
||||
import android.content.Context
|
||||
import android.support.annotation.DrawableRes
|
||||
import android.support.annotation.StringRes
|
||||
import ch.dissem.apps.abit.R
|
||||
import ch.dissem.bitmessage.entity.Plaintext
|
||||
import java.io.IOException
|
||||
|
@ -6,10 +6,7 @@ import android.app.job.JobScheduler
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.support.annotation.RequiresApi
|
||||
import android.support.v4.content.ContextCompat
|
||||
import ch.dissem.apps.abit.MainActivity
|
||||
import ch.dissem.apps.abit.dialog.FullNodeDialogActivity
|
||||
import ch.dissem.apps.abit.service.BitmessageService
|
||||
import ch.dissem.apps.abit.service.StartupNodeOnWifiService
|
||||
@ -20,36 +17,19 @@ object NetworkUtils {
|
||||
fun enableNode(ctx: Context, ask: Boolean = true) {
|
||||
Preferences.setFullNodeActive(ctx, true)
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
if (Preferences.isConnectionAllowed(ctx) || !ask) {
|
||||
scheduleNodeStart(ctx)
|
||||
} else {
|
||||
askForConnection(ctx)
|
||||
}
|
||||
if (Preferences.isConnectionAllowed(ctx) || !ask) {
|
||||
scheduleNodeStart(ctx)
|
||||
} else {
|
||||
if (Preferences.isWifiOnly(ctx)) {
|
||||
if (Preferences.isConnectionAllowed(ctx)) {
|
||||
doStartBitmessageService(ctx)
|
||||
MainActivity.updateNodeSwitch()
|
||||
} else if (ask) {
|
||||
askForConnection(ctx)
|
||||
}
|
||||
} else {
|
||||
doStartBitmessageService(ctx)
|
||||
MainActivity.updateNodeSwitch()
|
||||
// Ask for connection
|
||||
val dialogIntent = Intent(ctx, FullNodeDialogActivity::class.java)
|
||||
if (ctx !is Activity) {
|
||||
dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
ctx.sendBroadcast(Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS))
|
||||
}
|
||||
ctx.startActivity(dialogIntent)
|
||||
}
|
||||
}
|
||||
|
||||
private fun askForConnection(ctx: Context) {
|
||||
val dialogIntent = Intent(ctx, FullNodeDialogActivity::class.java)
|
||||
if (ctx !is Activity) {
|
||||
dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
ctx.sendBroadcast(Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS))
|
||||
}
|
||||
ctx.startActivity(dialogIntent)
|
||||
}
|
||||
|
||||
fun doStartBitmessageService(ctx: Context) {
|
||||
ContextCompat.startForegroundService(ctx, Intent(ctx, BitmessageService::class.java))
|
||||
}
|
||||
@ -59,7 +39,6 @@ object NetworkUtils {
|
||||
ctx.stopService(Intent(ctx, BitmessageService::class.java))
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
fun scheduleNodeStart(ctx: Context) {
|
||||
val jobScheduler = ctx.getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler
|
||||
val serviceComponent = ComponentName(ctx, StartupNodeOnWifiService::class.java)
|
||||
|
@ -1,25 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2015 Haruki Hasegawa
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item>
|
||||
<color android:color="@color/bg_swipe_item_trash"/>
|
||||
</item>
|
||||
<item
|
||||
android:drawable="@drawable/ic_item_swipe_trash"
|
||||
android:gravity="right|center_vertical"
|
||||
android:right="16dp"/>
|
||||
</layer-list>
|
@ -1,25 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2015 Haruki Hasegawa
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item>
|
||||
<color android:color="@color/bg_swipe_item_archive"/>
|
||||
</item>
|
||||
<item
|
||||
android:drawable="@drawable/ic_item_swipe_archive"
|
||||
android:gravity="left|center_vertical"
|
||||
android:left="16dp"/>
|
||||
</layer-list>
|
@ -1,9 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:color="#ffffff">
|
||||
|
||||
<item
|
||||
android:id="@android:id/mask"
|
||||
android:drawable="@android:color/white"/>
|
||||
|
||||
</ripple>
|
@ -18,9 +18,8 @@
|
||||
<item>
|
||||
<color android:color="@color/bg_swipe_item_trash"/>
|
||||
</item>
|
||||
<item android:right="16dp">
|
||||
<bitmap
|
||||
android:gravity="right|center_vertical"
|
||||
android:src="@drawable/ic_item_swipe_trash"/>
|
||||
</item>
|
||||
<item
|
||||
android:drawable="@drawable/ic_item_swipe_trash"
|
||||
android:gravity="right|center_vertical"
|
||||
android:right="16dp"/>
|
||||
</layer-list>
|
||||
|
@ -18,9 +18,8 @@
|
||||
<item>
|
||||
<color android:color="@color/bg_swipe_item_archive"/>
|
||||
</item>
|
||||
<item android:left="16dp">
|
||||
<bitmap
|
||||
android:gravity="left|center_vertical"
|
||||
android:src="@drawable/ic_item_swipe_archive"/>
|
||||
</item>
|
||||
<item
|
||||
android:drawable="@drawable/ic_item_swipe_archive"
|
||||
android:gravity="left|center_vertical"
|
||||
android:left="16dp"/>
|
||||
</layer-list>
|
||||
|
@ -1,14 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_pressed="true">
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="#ccffffff" />
|
||||
</shape>
|
||||
</item>
|
||||
<item android:state_focused="true">
|
||||
<shape android:shape="rectangle">
|
||||
<stroke android:color="@android:color/white" />
|
||||
</shape>
|
||||
</item>
|
||||
<item android:drawable="@android:color/transparent" />
|
||||
</selector>
|
||||
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:color="#ffffff">
|
||||
|
||||
<item
|
||||
android:id="@android:id/mask"
|
||||
android:drawable="@android:color/white"/>
|
||||
|
||||
</ripple>
|
@ -1,11 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Button xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/material_showcase_button_bg"
|
||||
android:text="@string/got_it"
|
||||
android:textAllCaps="true"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="13sp"
|
||||
android:textStyle="bold">
|
||||
</Button>
|
@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<bool name="is_pre_api_21">false</bool>
|
||||
<bool name="is_post_api_21">true</bool>
|
||||
</resources>
|
@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<bool name="is_pre_api_21">true</bool>
|
||||
<bool name="is_post_api_21">false</bool>
|
||||
</resources>
|
@ -34,7 +34,6 @@
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:key="require_charging"
|
||||
android:enabled="@bool/is_post_api_21"
|
||||
android:summary="@string/require_charging_summary"
|
||||
android:title="@string/require_charging" />
|
||||
<SwitchPreferenceCompat
|
||||
|
Loading…
Reference in New Issue
Block a user