forked from upstream-mirrors/quik
Migrate services and receivers to data package
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Moez Bhatti <moez.bhatti@gmail.com>
|
||||
*
|
||||
* This file is part of QKSMS.
|
||||
*
|
||||
* QKSMS is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* QKSMS is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with QKSMS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package receiver
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.provider.Telephony
|
||||
import android.support.annotation.RequiresApi
|
||||
import dagger.android.AndroidInjection
|
||||
import interactor.SyncMessages
|
||||
import util.Preferences
|
||||
import javax.inject.Inject
|
||||
|
||||
class DefaultSmsChangedReceiver : BroadcastReceiver() {
|
||||
|
||||
@Inject lateinit var prefs: Preferences
|
||||
@Inject lateinit var syncMessages: SyncMessages
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.N)
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
AndroidInjection.inject(this, context)
|
||||
|
||||
if (intent.getBooleanExtra(Telephony.Sms.Intents.EXTRA_IS_DEFAULT_SMS_APP, false)) {
|
||||
val pendingResult = goAsync()
|
||||
syncMessages.execute(Unit, { pendingResult.finish() })
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Moez Bhatti <moez.bhatti@gmail.com>
|
||||
*
|
||||
* This file is part of QKSMS.
|
||||
*
|
||||
* QKSMS is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* QKSMS is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with QKSMS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package receiver
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import dagger.android.AndroidInjection
|
||||
import interactor.MarkRead
|
||||
import javax.inject.Inject
|
||||
|
||||
class MarkReadReceiver : BroadcastReceiver() {
|
||||
|
||||
@Inject lateinit var markRead: MarkRead
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
AndroidInjection.inject(this, context)
|
||||
|
||||
val threadId = intent.getLongExtra("threadId", 0)
|
||||
markRead.execute(threadId)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Moez Bhatti <moez.bhatti@gmail.com>
|
||||
*
|
||||
* This file is part of QKSMS.
|
||||
*
|
||||
* QKSMS is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* QKSMS is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with QKSMS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package receiver
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import dagger.android.AndroidInjection
|
||||
import interactor.MarkSeen
|
||||
import javax.inject.Inject
|
||||
|
||||
class MarkSeenReceiver : BroadcastReceiver() {
|
||||
|
||||
@Inject lateinit var markSeen: MarkSeen
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
AndroidInjection.inject(this, context)
|
||||
|
||||
val threadId = intent.getLongExtra("threadId", 0)
|
||||
markSeen.execute(threadId)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Moez Bhatti <moez.bhatti@gmail.com>
|
||||
*
|
||||
* This file is part of QKSMS.
|
||||
*
|
||||
* QKSMS is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* QKSMS is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with QKSMS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package receiver
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import com.klinker.android.send_message.MmsReceivedReceiver
|
||||
import dagger.android.AndroidInjection
|
||||
import interactor.ReceiveMms
|
||||
import javax.inject.Inject
|
||||
|
||||
class MmsReceivedReceiver : MmsReceivedReceiver() {
|
||||
|
||||
@Inject lateinit var receiveMms: ReceiveMms
|
||||
|
||||
override fun onReceive(context: Context?, intent: Intent?) {
|
||||
AndroidInjection.inject(this, context)
|
||||
super.onReceive(context, intent)
|
||||
}
|
||||
|
||||
override fun onMessageReceived(messageUri: Uri?) {
|
||||
messageUri?.let { uri ->
|
||||
val pendingResult = goAsync()
|
||||
receiveMms.execute(uri) { pendingResult.finish() }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Moez Bhatti <moez.bhatti@gmail.com>
|
||||
*
|
||||
* This file is part of QKSMS.
|
||||
*
|
||||
* QKSMS is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* QKSMS is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with QKSMS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package receiver
|
||||
|
||||
import com.android.mms.transaction.PushReceiver
|
||||
|
||||
class MmsReceiver : PushReceiver()
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Moez Bhatti <moez.bhatti@gmail.com>
|
||||
*
|
||||
* This file is part of QKSMS.
|
||||
*
|
||||
* QKSMS is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* QKSMS is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with QKSMS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package receiver
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.ContentUris
|
||||
import android.content.ContentValues
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.provider.Telephony
|
||||
import com.google.android.mms.MmsException
|
||||
import com.google.android.mms.util_alt.SqliteWrapper
|
||||
import com.klinker.android.send_message.Transaction
|
||||
import dagger.android.AndroidInjection
|
||||
import interactor.SyncMessage
|
||||
import timber.log.Timber
|
||||
import java.io.File
|
||||
import javax.inject.Inject
|
||||
|
||||
class MmsSentReceiver : BroadcastReceiver() {
|
||||
|
||||
@Inject lateinit var syncMessage: SyncMessage
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
AndroidInjection.inject(this, context)
|
||||
|
||||
Timber.v("MMS sending result: $resultCode")
|
||||
val uri = Uri.parse(intent.getStringExtra(Transaction.EXTRA_CONTENT_URI))
|
||||
Timber.v(uri.toString())
|
||||
|
||||
when (resultCode) {
|
||||
Activity.RESULT_OK -> {
|
||||
Timber.v("MMS has finished sending, marking it as so in the database")
|
||||
val values = ContentValues(1)
|
||||
values.put(Telephony.Mms.MESSAGE_BOX, Telephony.Mms.MESSAGE_BOX_SENT)
|
||||
SqliteWrapper.update(context, context.contentResolver, uri, values, null, null)
|
||||
}
|
||||
|
||||
else -> {
|
||||
Timber.v("MMS has failed to send, marking it as so in the database")
|
||||
try {
|
||||
val messageId = ContentUris.parseId(uri)
|
||||
|
||||
val values = ContentValues(1)
|
||||
values.put(Telephony.Mms.MESSAGE_BOX, Telephony.Mms.MESSAGE_BOX_FAILED)
|
||||
SqliteWrapper.update(context, context.contentResolver, Telephony.Mms.CONTENT_URI, values,
|
||||
"${Telephony.Mms._ID} = ?", arrayOf(messageId.toString()))
|
||||
|
||||
// TODO this query isn't able to find any results
|
||||
// Need to figure out why the message isn't appearing in the PendingMessages Uri,
|
||||
// so that we can properly assign the error type
|
||||
val errorTypeValues = ContentValues(1)
|
||||
errorTypeValues.put(Telephony.MmsSms.PendingMessages.ERROR_TYPE, Telephony.MmsSms.ERR_TYPE_GENERIC_PERMANENT)
|
||||
SqliteWrapper.update(context, context.contentResolver, Telephony.MmsSms.PendingMessages.CONTENT_URI,
|
||||
errorTypeValues, "${Telephony.MmsSms.PendingMessages.MSG_ID} = ?", arrayOf(messageId.toString()))
|
||||
|
||||
} catch (e: MmsException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val filePath = intent.getStringExtra(Transaction.EXTRA_FILE_PATH)
|
||||
Timber.v(filePath)
|
||||
File(filePath).delete()
|
||||
|
||||
Uri.parse(intent.getStringExtra("content_uri"))?.let { uri ->
|
||||
val pendingResult = goAsync()
|
||||
syncMessage.execute(uri) { pendingResult.finish() }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Moez Bhatti <moez.bhatti@gmail.com>
|
||||
*
|
||||
* This file is part of QKSMS.
|
||||
*
|
||||
* QKSMS is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* QKSMS is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with QKSMS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package receiver
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import dagger.android.AndroidInjection
|
||||
import interactor.SyncMessage
|
||||
import javax.inject.Inject
|
||||
|
||||
class MmsUpdatedReceiver : BroadcastReceiver() {
|
||||
|
||||
companion object {
|
||||
const val URI = "uri"
|
||||
}
|
||||
|
||||
@Inject lateinit var syncMessage: SyncMessage
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
AndroidInjection.inject(this, context)
|
||||
|
||||
intent.getStringExtra(URI)?.let { uriString ->
|
||||
val pendingResult = goAsync()
|
||||
syncMessage.execute(Uri.parse(uriString)) { pendingResult.finish() }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Moez Bhatti <moez.bhatti@gmail.com>
|
||||
*
|
||||
* This file is part of QKSMS.
|
||||
*
|
||||
* QKSMS is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* QKSMS is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with QKSMS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package receiver
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import dagger.android.AndroidInjection
|
||||
import util.NightModeManager
|
||||
import javax.inject.Inject
|
||||
|
||||
class NightModeReceiver : BroadcastReceiver() {
|
||||
|
||||
@Inject lateinit var nightModeManager: NightModeManager
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
AndroidInjection.inject(this, context)
|
||||
|
||||
nightModeManager.updateCurrentTheme()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Moez Bhatti <moez.bhatti@gmail.com>
|
||||
*
|
||||
* This file is part of QKSMS.
|
||||
*
|
||||
* QKSMS is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* QKSMS is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with QKSMS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package receiver
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.support.v4.app.RemoteInput
|
||||
import dagger.android.AndroidInjection
|
||||
import interactor.MarkRead
|
||||
import interactor.SendMessage
|
||||
import javax.inject.Inject
|
||||
|
||||
class RemoteMessagingReceiver : BroadcastReceiver() {
|
||||
|
||||
@Inject lateinit var sendMessage: SendMessage
|
||||
@Inject lateinit var markRead: MarkRead
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
AndroidInjection.inject(this, context)
|
||||
|
||||
val remoteInput = RemoteInput.getResultsFromIntent(intent)
|
||||
val bundle = intent.extras
|
||||
if (remoteInput != null && bundle != null) {
|
||||
val address = bundle.getString("address")
|
||||
val threadId = bundle.getLong("threadId")
|
||||
val body = remoteInput.getCharSequence("body").toString()
|
||||
markRead.execute(threadId)
|
||||
sendMessage.execute(SendMessage.Params(threadId, listOf(address), body))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Moez Bhatti <moez.bhatti@gmail.com>
|
||||
*
|
||||
* This file is part of QKSMS.
|
||||
*
|
||||
* QKSMS is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* QKSMS is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with QKSMS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package receiver
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import dagger.android.AndroidInjection
|
||||
import interactor.RetrySending
|
||||
import repository.MessageRepository
|
||||
import javax.inject.Inject
|
||||
|
||||
class SendSmsReceiver : BroadcastReceiver() {
|
||||
|
||||
@Inject lateinit var messageRepo: MessageRepository
|
||||
@Inject lateinit var retrySending: RetrySending
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
AndroidInjection.inject(this, context)
|
||||
|
||||
val id = intent.getLongExtra("id", 0L)
|
||||
messageRepo.getMessage(id)?.let { message ->
|
||||
val result = goAsync()
|
||||
retrySending.execute(message) { result.finish() }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Moez Bhatti <moez.bhatti@gmail.com>
|
||||
*
|
||||
* This file is part of QKSMS.
|
||||
*
|
||||
* QKSMS is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* QKSMS is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with QKSMS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package receiver
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import dagger.android.AndroidInjection
|
||||
import interactor.MarkDelivered
|
||||
import interactor.MarkDeliveryFailed
|
||||
import javax.inject.Inject
|
||||
|
||||
class SmsDeliveredReceiver : BroadcastReceiver() {
|
||||
|
||||
@Inject lateinit var markDelivered: MarkDelivered
|
||||
@Inject lateinit var markDeliveryFailed: MarkDeliveryFailed
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
AndroidInjection.inject(this, context)
|
||||
|
||||
val id = intent.getLongExtra("id", 0L)
|
||||
|
||||
when (resultCode) {
|
||||
// TODO notify about delivery
|
||||
Activity.RESULT_OK -> {
|
||||
val pendingResult = goAsync()
|
||||
markDelivered.execute(id) { pendingResult.finish() }
|
||||
}
|
||||
|
||||
// TODO notify about delivery failure
|
||||
Activity.RESULT_CANCELED -> {
|
||||
val pendingResult = goAsync()
|
||||
markDeliveryFailed.execute(MarkDeliveryFailed.Params(id, resultCode)) { pendingResult.finish() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Moez Bhatti <moez.bhatti@gmail.com>
|
||||
*
|
||||
* This file is part of QKSMS.
|
||||
*
|
||||
* QKSMS is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* QKSMS is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with QKSMS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package receiver
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import dagger.android.AndroidInjection
|
||||
import interactor.SyncMessage
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* When the SMS contentprovider is changed by a process other than us, we need to sync the Uri that
|
||||
* was changed.
|
||||
*
|
||||
* This can happen if a message is sent through something like Pushbullet or Google Assistant.
|
||||
*
|
||||
* This only works on API 24+, so to fully solve this problem we'll need a smarter way of running
|
||||
* partial syncs on older devices.
|
||||
*
|
||||
* https://developer.android.com/reference/android/provider/Telephony.Sms.Intents.html#ACTION_EXTERNAL_PROVIDER_CHANGE
|
||||
*/
|
||||
class SmsProviderChangedReceiver : BroadcastReceiver() {
|
||||
|
||||
@Inject lateinit var syncMessage: SyncMessage
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
AndroidInjection.inject(this, context)
|
||||
|
||||
// Obtain the uri for the changed data
|
||||
// If the value is null, don't continue
|
||||
val uri = intent.data ?: return
|
||||
|
||||
// Sync the message to our realm
|
||||
val pendingResult = goAsync()
|
||||
syncMessage.execute(uri) { pendingResult.finish() }
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Moez Bhatti <moez.bhatti@gmail.com>
|
||||
*
|
||||
* This file is part of QKSMS.
|
||||
*
|
||||
* QKSMS is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* QKSMS is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with QKSMS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package receiver
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.provider.Telephony.Sms
|
||||
import dagger.android.AndroidInjection
|
||||
import interactor.ReceiveSms
|
||||
import javax.inject.Inject
|
||||
|
||||
class SmsReceiver : BroadcastReceiver() {
|
||||
|
||||
@Inject lateinit var receiveMessage: ReceiveSms
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
AndroidInjection.inject(this, context)
|
||||
|
||||
Sms.Intents.getMessagesFromIntent(intent)?.let { messages ->
|
||||
val pendingResult = goAsync()
|
||||
receiveMessage.execute(messages, { pendingResult.finish() })
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Moez Bhatti <moez.bhatti@gmail.com>
|
||||
*
|
||||
* This file is part of QKSMS.
|
||||
*
|
||||
* QKSMS is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* QKSMS is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with QKSMS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package receiver
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.telephony.SmsManager
|
||||
import dagger.android.AndroidInjection
|
||||
import interactor.MarkFailed
|
||||
import interactor.MarkSent
|
||||
import javax.inject.Inject
|
||||
|
||||
class SmsSentReceiver : BroadcastReceiver() {
|
||||
|
||||
@Inject lateinit var markSent: MarkSent
|
||||
@Inject lateinit var markFailed: MarkFailed
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
AndroidInjection.inject(this, context)
|
||||
|
||||
val id = intent.getLongExtra("id", 0L)
|
||||
|
||||
when (resultCode) {
|
||||
Activity.RESULT_OK -> {
|
||||
val pendingResult = goAsync()
|
||||
markSent.execute(id) { pendingResult.finish() }
|
||||
}
|
||||
|
||||
SmsManager.RESULT_ERROR_GENERIC_FAILURE,
|
||||
SmsManager.RESULT_ERROR_NO_SERVICE,
|
||||
SmsManager.RESULT_ERROR_NULL_PDU,
|
||||
SmsManager.RESULT_ERROR_RADIO_OFF -> {
|
||||
val pendingResult = goAsync()
|
||||
markFailed.execute(MarkFailed.Params(id, resultCode)) { pendingResult.finish() }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,14 +24,18 @@ import android.content.ContentUris
|
||||
import android.content.ContentValues
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Bitmap
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.provider.BaseColumns
|
||||
import android.provider.Telephony
|
||||
import android.telephony.PhoneNumberUtils
|
||||
import android.telephony.SmsManager
|
||||
import com.google.android.mms.ContentType
|
||||
import com.klinker.android.send_message.BroadcastUtils
|
||||
import com.klinker.android.send_message.Settings
|
||||
import com.klinker.android.send_message.StripAccents
|
||||
import com.klinker.android.send_message.Transaction
|
||||
import filter.ConversationFilter
|
||||
import io.reactivex.Maybe
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
@@ -43,6 +47,7 @@ import io.realm.Sort
|
||||
import manager.KeyManager
|
||||
import mapper.CursorToConversation
|
||||
import mapper.CursorToRecipient
|
||||
import model.Attachment
|
||||
import model.Contact
|
||||
import model.Conversation
|
||||
import model.Message
|
||||
@@ -54,6 +59,7 @@ import util.extensions.anyOf
|
||||
import util.extensions.asMaybe
|
||||
import util.extensions.insertOrUpdate
|
||||
import util.extensions.map
|
||||
import java.io.ByteArrayOutputStream
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@@ -64,6 +70,7 @@ class MessageRepositoryImpl @Inject constructor(
|
||||
private val conversationFilter: ConversationFilter,
|
||||
private val cursorToConversation: CursorToConversation,
|
||||
private val cursorToRecipient: CursorToRecipient,
|
||||
private val imageRepository: ImageRepository,
|
||||
private val prefs: Preferences) : MessageRepository {
|
||||
|
||||
override fun getConversations(archived: Boolean): RealmResults<Conversation> {
|
||||
@@ -104,7 +111,7 @@ class MessageRepositoryImpl @Inject constructor(
|
||||
.sortedByDescending { result -> result.messages }
|
||||
|
||||
return conversations
|
||||
.filter { conversation -> conversationFilter.filter(conversation, query) }
|
||||
.filter { conversation -> conversationFilter.filter(conversation, query) }
|
||||
.map { conversation -> SearchResult(query, conversation, 0) }
|
||||
.plus(messagesByConversation)
|
||||
}
|
||||
@@ -436,6 +443,60 @@ class MessageRepositoryImpl @Inject constructor(
|
||||
smsManager.sendMultipartTextMessage(message.address, null, parts, ArrayList(sentIntents), ArrayList(deliveredIntents))
|
||||
}
|
||||
|
||||
override fun sendMms(threadId: Long, addresses: List<String>, body: String, attachments: List<Attachment>) {
|
||||
val settings = Settings()
|
||||
val message = com.klinker.android.send_message.Message(body, addresses.toTypedArray())
|
||||
|
||||
// Add the GIFs as attachments. The app currently can't compress them, which may result
|
||||
// in a lot of these messages failing to send
|
||||
// TODO Add support for GIF compression
|
||||
attachments
|
||||
.filter { attachment -> attachment.isGif(context) }
|
||||
.map { attachment -> attachment.getUri() }
|
||||
.map { uri -> context.contentResolver.openInputStream(uri) }
|
||||
.map { inputStream -> inputStream.readBytes() }
|
||||
.forEach { bitmap -> message.addMedia(bitmap, ContentType.IMAGE_GIF) }
|
||||
|
||||
// Compress the images and add them as attachments
|
||||
var totalImageBytes = 0
|
||||
attachments
|
||||
.filter { attachment -> !attachment.isGif(context) }
|
||||
.mapNotNull { attachment -> attachment.getUri() }
|
||||
.mapNotNull { uri -> imageRepository.loadImage(uri) }
|
||||
.also { totalImageBytes = it.sumBy { it.allocationByteCount } }
|
||||
.map { bitmap ->
|
||||
val byteRatio = bitmap.allocationByteCount / totalImageBytes.toFloat()
|
||||
shrink(bitmap, (prefs.mmsSize.get() * 1024 * byteRatio).toInt())
|
||||
}
|
||||
.forEach { bitmap -> message.addMedia(bitmap, ContentType.IMAGE_JPEG) }
|
||||
|
||||
val transaction = Transaction(context, settings)
|
||||
transaction.sendNewMessage(message, threadId)
|
||||
}
|
||||
|
||||
private fun shrink(src: Bitmap, maxBytes: Int): ByteArray {
|
||||
var step = 0.0
|
||||
val factor = 0.5
|
||||
val quality = 60
|
||||
|
||||
val height = src.height
|
||||
val width = src.width
|
||||
|
||||
val stream = ByteArrayOutputStream()
|
||||
src.compress(Bitmap.CompressFormat.JPEG, 100, stream)
|
||||
|
||||
while (maxBytes > 0 && stream.size() > maxBytes) {
|
||||
step++
|
||||
val scale = Math.pow(factor, step)
|
||||
|
||||
stream.reset()
|
||||
Bitmap.createScaledBitmap(src, (width * scale).toInt(), (height * scale).toInt(), false)
|
||||
.compress(Bitmap.CompressFormat.JPEG, quality, stream)
|
||||
}
|
||||
|
||||
return stream.toByteArray()
|
||||
}
|
||||
|
||||
override fun cancelDelayedSms(id: Long) {
|
||||
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
|
||||
alarmManager.cancel(getIntentForDelayedSms(id))
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Moez Bhatti <moez.bhatti@gmail.com>
|
||||
*
|
||||
* This file is part of QKSMS.
|
||||
*
|
||||
* QKSMS is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* QKSMS is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with QKSMS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package service
|
||||
|
||||
import android.app.IntentService
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.telephony.TelephonyManager
|
||||
import dagger.android.AndroidInjection
|
||||
import interactor.SendMessage
|
||||
import repository.MessageRepository
|
||||
import javax.inject.Inject
|
||||
|
||||
class HeadlessSmsSendService : IntentService("HeadlessSmsSendService") {
|
||||
|
||||
@Inject lateinit var messageRepo: MessageRepository
|
||||
@Inject lateinit var sendMessage: SendMessage
|
||||
|
||||
override fun onHandleIntent(intent: Intent?) {
|
||||
if (intent?.action != TelephonyManager.ACTION_RESPOND_VIA_MESSAGE) return
|
||||
|
||||
AndroidInjection.inject(this)
|
||||
intent.extras?.getString(Intent.EXTRA_TEXT)?.takeIf { it.isNotBlank() }?.let { body ->
|
||||
val intentUri = intent.data
|
||||
val recipients = getRecipients(intentUri).split(";")
|
||||
val threadId = messageRepo.getOrCreateConversation(recipients).blockingGet()?.id ?: 0L
|
||||
sendMessage.execute(SendMessage.Params(threadId, recipients, body))
|
||||
}
|
||||
}
|
||||
|
||||
private fun getRecipients(uri: Uri): String {
|
||||
val base = uri.schemeSpecificPart
|
||||
val position = base.indexOf('?')
|
||||
return if (position == -1) base else base.substring(0, position)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Moez Bhatti <moez.bhatti@gmail.com>
|
||||
*
|
||||
* This file is part of QKSMS.
|
||||
*
|
||||
* QKSMS is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* QKSMS is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with QKSMS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package util
|
||||
|
||||
import android.app.AlarmManager
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import receiver.NightModeReceiver
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class NightModeManager @Inject constructor(
|
||||
private val context: Context,
|
||||
private val prefs: Preferences) {
|
||||
|
||||
fun updateCurrentTheme() {
|
||||
// If night mode is not on auto, then there's nothing to do here
|
||||
if (prefs.nightMode.get() != Preferences.NIGHT_MODE_AUTO) {
|
||||
return
|
||||
}
|
||||
|
||||
val nightStartTime = getPreviousInstanceOfTime(prefs.nightStart.get())
|
||||
val nightEndTime = getPreviousInstanceOfTime(prefs.nightEnd.get())
|
||||
|
||||
// If the last nightStart was more recent than the last nightEnd, then it's night time
|
||||
prefs.night.set(nightStartTime > nightEndTime)
|
||||
}
|
||||
|
||||
fun updateNightMode(mode: Int) {
|
||||
prefs.nightMode.set(mode)
|
||||
|
||||
// If it's not on auto mode, set the appropriate night mode
|
||||
if (mode != Preferences.NIGHT_MODE_AUTO) {
|
||||
prefs.night.set(mode == Preferences.NIGHT_MODE_ON)
|
||||
}
|
||||
|
||||
updateAlarms()
|
||||
}
|
||||
|
||||
fun setNightStart(hour: Int, minute: Int) {
|
||||
prefs.nightStart.set("$hour:$minute")
|
||||
updateAlarms()
|
||||
}
|
||||
|
||||
fun setNightEnd(hour: Int, minute: Int) {
|
||||
prefs.nightEnd.set("$hour:$minute")
|
||||
updateAlarms()
|
||||
}
|
||||
|
||||
private fun updateAlarms() {
|
||||
val dayCalendar = createCalendar(prefs.nightEnd.get())
|
||||
val day = Intent(context, NightModeReceiver::class.java)
|
||||
val dayIntent = PendingIntent.getBroadcast(context, 0, day, 0)
|
||||
|
||||
val nightCalendar = createCalendar(prefs.nightStart.get())
|
||||
val night = Intent(context, NightModeReceiver::class.java)
|
||||
val nightIntent = PendingIntent.getBroadcast(context, 1, night, 0)
|
||||
|
||||
context.sendBroadcast(day)
|
||||
context.sendBroadcast(night)
|
||||
|
||||
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
|
||||
if (prefs.nightMode.get() == Preferences.NIGHT_MODE_AUTO) {
|
||||
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, dayCalendar.timeInMillis, AlarmManager.INTERVAL_DAY, dayIntent)
|
||||
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, nightCalendar.timeInMillis, AlarmManager.INTERVAL_DAY, nightIntent)
|
||||
} else {
|
||||
alarmManager.cancel(dayIntent)
|
||||
alarmManager.cancel(nightIntent)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createCalendar(time: String): Calendar {
|
||||
val calendar = parseTime(time)
|
||||
|
||||
return Calendar.getInstance().apply {
|
||||
set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY))
|
||||
set(Calendar.MINUTE, calendar.get(Calendar.MINUTE))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the hour and minute out of the [time], which should be formatted h:mm
|
||||
*/
|
||||
fun parseTime(time: String): Calendar {
|
||||
return tryOrNull {
|
||||
val parsedTime = SimpleDateFormat("H:mm", Locale.US).parse(time)
|
||||
Calendar.getInstance().apply { this.time = parsedTime }
|
||||
} ?: tryOrNull {
|
||||
// Parse the legacy timestamp format (<=3.1.3)
|
||||
val parsedTime = SimpleDateFormat("h:mm a", Locale.US).parse(time)
|
||||
Calendar.getInstance().apply { this.time = parsedTime }
|
||||
} ?: Calendar.getInstance().apply { set(Calendar.HOUR_OF_DAY, 18) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Calendar set to the most recent occurrence of this time
|
||||
*/
|
||||
private fun getPreviousInstanceOfTime(time: String): Calendar {
|
||||
val currentTime = System.currentTimeMillis() + TimeUnit.MINUTES.toMillis(10)
|
||||
val calendar = createCalendar(time)
|
||||
|
||||
while (calendar.timeInMillis > currentTime) {
|
||||
calendar.add(Calendar.DAY_OF_YEAR, -1)
|
||||
}
|
||||
|
||||
return calendar
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user