c'est presque bon, je sais pas encore où je vais trouver le temps de tout faire tho

This commit is contained in:
odrling 2018-04-02 03:37:32 +02:00
parent e9b8e5020f
commit 7678e79fee
7 changed files with 388 additions and 245 deletions

View file

@ -17,6 +17,7 @@
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:allowBackup="false"
@ -51,14 +52,19 @@
</intent-filter>
</receiver>
<receiver android:name=".messages.NornMMSReceiver"
<receiver
android:name="com.android.mms.transaction.PushReceiver"
android:permission="android.permission.BROADCAST_WAP_PUSH">
<intent-filter android:priority="999">
<intent-filter>
<action android:name="android.provider.Telephony.WAP_PUSH_DELIVER" />
<data android:mimeType="application/vnd.wap.mms-message" />
</intent-filter>
</receiver>
<receiver
android:name=".messages.NornMMSReceiver"
android:taskAffinity="com.klinker.android.messaging.MMS_RECEIVED" />
<receiver android:name=".messages.NornLocaleChangedReceiver">
<intent-filter>
<action android:name="android.intent.action.LOCALE_CHANGED"/>

View file

@ -26,7 +26,7 @@ class ComposeActivity : ComposeView.SendActivity() {
companion object {
class SendTask(context: Context, val number: String, val text: String, val medias: ArrayList<NornMedia>) : AsyncTask<Void, Void, NornMessage?>() {
class SendTask(context: Context, val number: String, val text: String, private val medias: Array<NornMedia>) : AsyncTask<Void, Void, NornMessage?>() {
val context = WeakReference<Context>(context)
@ -76,7 +76,7 @@ class ComposeActivity : ComposeView.SendActivity() {
override val layout = R.layout.activity_compose
override fun sendMessage(text: String, medias: ArrayList<NornMedia>) {
override fun sendMessage(text: String, medias: Array<NornMedia>) {
// trouver le destinataire saisi par l'utilisateur
val dest = number.text.toString()

View file

@ -67,7 +67,7 @@ class ConversationActivity: ComposeView.SendActivity() {
}
class SendTask(activity: ConversationActivity, val text: String, val medias: ArrayList<NornMedia>) : AsyncTask<Void, Void, NornMessage?>() {
class SendTask(activity: ConversationActivity, val text: String, private val medias: Array<NornMedia>) : AsyncTask<Void, Void, NornMessage?>() {
val activity = WeakReference<ConversationActivity>(activity)
@ -143,7 +143,7 @@ class ConversationActivity: ComposeView.SendActivity() {
this.title = this.conversation.name
}
override fun sendMessage(text: String, medias: ArrayList<NornMedia>) {
override fun sendMessage(text: String, medias: Array<NornMedia>) {
// envoyer le message en arrière plan
SendTask(this, text, medias).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR)
}

View file

@ -1,19 +1,376 @@
/*
* Copyright (C) 2015 Jacob Klinker
*
* 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 xyz.johnny.norntalk.messages
import android.content.BroadcastReceiver
import android.content.ContentResolver
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.AsyncTask
import android.os.Parcelable
import android.provider.Telephony
import android.telephony.SmsManager
import android.util.Log
import android.widget.Toast
import com.android.mms.service_alt.MmsConfig
import com.android.mms.transaction.DownloadManager
import com.android.mms.transaction.HttpUtils
import com.android.mms.transaction.TransactionSettings
import com.android.mms.util.SendingProgressTokenManager
import com.google.android.mms.InvalidHeaderValueException
import com.google.android.mms.MmsException
import com.google.android.mms.pdu_alt.*
import com.google.android.mms.pdu_alt.PduHeaders.STATUS_RETRIEVED
import com.google.android.mms.util_alt.SqliteWrapper
import com.klinker.android.send_message.Utils
import java.io.*
import java.lang.ref.WeakReference
import java.nio.charset.Charset
import java.util.*
import java.util.concurrent.Executors
/**
* Classe recevant les MMS.
*/
class NornMMSReceiver: BroadcastReceiver() {
class NornMMSReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
Log.d(this::class.java.simpleName, "MMS received")
Toast.makeText(context, "MMS received", Toast.LENGTH_LONG).show()
// Override this and provide the MMSC to send the ACK to.
// some carriers will download duplicate MMS messages without this ACK. When using the
// system sending method, apparently Google does not do this for us. Not sure why.
// You might have to have users manually enter their APN settings if you cannot get them
// from the system somehow.
val mmscInfoForReceptionAck: MmscInformation?
get() = null
override fun onReceive(context: Context, intent: Intent) {
Log.d(TAG, "MMS has finished downloading, persisting it to the database")
val path = intent.getStringExtra(EXTRA_FILE_PATH)
Log.d(TAG, path)
var errorMessage: String? = null
try {
val mDownloadFile = File(path)
val nBytes = mDownloadFile.length().toInt()
FileInputStream(mDownloadFile).use { reader ->
val response = ByteArray(nBytes)
reader.read(response, 0, nBytes)
val tasks = getNotificationTask(context, intent, response)
val pdu = PduParser(response).parse() as RetrieveConf
val message = this.createMessage(context, pdu)
message.insertMessage(context)
NornMessageDispatcher.send(message)
Log.v(TAG, "response saved successfully")
Log.v(TAG, "response length: " + response.size)
mDownloadFile.delete()
if (tasks != null) {
Log.v(TAG, "running the common async notifier for download")
for (task in tasks)
task.executeOnExecutor(RECEIVE_NOTIFICATION_EXECUTOR)
}
}
} catch (e: FileNotFoundException) {
errorMessage = "MMS received, file not found exception"
Log.e(TAG, errorMessage, e)
} catch (e: IOException) {
errorMessage = "MMS received, io exception"
Log.e(TAG, errorMessage, e)
}
handleHttpError(context, intent)
DownloadManager.finishDownload(intent.getStringExtra(EXTRA_LOCATION_URL))
if (errorMessage != null) {
onError(errorMessage)
}
}
}
fun createMessage(context: Context, pdu: RetrieveConf): NornMessage {
val medias = ArrayList<NornMedia>()
var text = ""
for (i in 0..(pdu.body.partsNum - 1)) {
val part = pdu.body.getPart(i)
val mimeType = part.contentType!!.toString(Charset.defaultCharset())
if (mimeType.startsWith("image")) {
val uri = this.writeFile(context, part.data)
medias.add(NornMedia(context, mimeType, uri))
} else if (mimeType == "text/plain")
text = part.data.toString(Charset.defaultCharset())
}
val addresses = setOf(pdu.from.string).plus(pdu.to.map { it.string }.toTypedArray())
val members = addresses.map { NornContact.getContact(it, context) }.toTypedArray()
val conversation = NornConversation.getConversation(members, context)
val message = NornMessage(text, conversation, Date(), context)
for (media in medias)
message.medias.add(media)
return message
}
fun writeFile(context: Context, data: ByteArray): Uri {
val fileName = "media." + System.currentTimeMillis() + "_" + Math.abs(Random().nextInt()).toString() + ".dat"
val file = File(context.cacheDir, fileName)
val writerUri = Uri.Builder()
.authority("xyz.johnny.norntalk.messages.NornMMSFileProvider")
.path(fileName)
.scheme(ContentResolver.SCHEME_CONTENT)
.build()
FileOutputStream(file).use { writer ->
writer.write(data)
}
val uri = writerUri
return uri
}
protected fun onError(error: String) {
}
private fun handleHttpError(context: Context, intent: Intent) {
val httpError = intent.getIntExtra(SmsManager.EXTRA_MMS_HTTP_STATUS, 0)
if (httpError == 404 || httpError == 400) {
// Delete the corresponding NotificationInd
SqliteWrapper.delete(context,
context.contentResolver,
Telephony.Mms.CONTENT_URI,
LOCATION_SELECTION,
arrayOf(Integer.toString(PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND), intent.getStringExtra(EXTRA_LOCATION_URL)))
}
}
private abstract class CommonAsyncTask internal constructor(context: Context, protected val mTransactionSettings: TransactionSettings, internal val mNotificationInd: NotificationInd) : AsyncTask<Void, Void, Void>() {
private val context = WeakReference<Context>(context)
internal val mContentLocation: String
init {
mContentLocation = String(mNotificationInd.contentLocation)
}
/**
* A common method to send a PDU to MMSC.
*
* @param pdu A byte array which contains the data of the PDU.
* @param mmscUrl Url of the recipient MMSC.
* @return A byte array which contains the response data.
* If an HTTP error code is returned, an IOException will be thrown.
* @throws java.io.IOException if any error occurred on network interface or
* an HTTP error code(>=400) returned from the server.
* @throws com.google.android.mms.MmsException if pdu is null.
*/
@Throws(IOException::class, MmsException::class)
internal fun sendPdu(pdu: ByteArray, mmscUrl: String): ByteArray {
return sendPdu(SendingProgressTokenManager.NO_TOKEN, pdu, mmscUrl)
}
/**
* A common method to send a PDU to MMSC.
*
* @param pdu A byte array which contains the data of the PDU.
* @return A byte array which contains the response data.
* If an HTTP error code is returned, an IOException will be thrown.
* @throws java.io.IOException if any error occurred on network interface or
* an HTTP error code(>=400) returned from the server.
* @throws com.google.android.mms.MmsException if pdu is null.
*/
@Throws(IOException::class, MmsException::class)
internal fun sendPdu(pdu: ByteArray): ByteArray {
return sendPdu(SendingProgressTokenManager.NO_TOKEN, pdu,
mTransactionSettings.mmscUrl)
}
/**
* A common method to send a PDU to MMSC.
*
* @param token The token to identify the sending progress.
* @param pdu A byte array which contains the data of the PDU.
* @param mmscUrl Url of the recipient MMSC.
* @return A byte array which contains the response data.
* If an HTTP error code is returned, an IOException will be thrown.
* @throws java.io.IOException if any error occurred on network interface or
* an HTTP error code(>=400) returned from the server.
* @throws com.google.android.mms.MmsException if pdu is null.
*/
@Throws(IOException::class, MmsException::class)
private fun sendPdu(token: Long, pdu: ByteArray?,
mmscUrl: String?): ByteArray {
if (pdu == null) {
throw MmsException()
}
if (mmscUrl == null) {
throw IOException("Cannot establish route: mmscUrl is null")
}
val mContext = this.context.get()
if (com.android.mms.transaction.Transaction.useWifi(mContext)) {
return HttpUtils.httpConnection(
mContext, token,
mmscUrl,
pdu, HttpUtils.HTTP_POST_METHOD,
false, null, 0)
}
Utils.ensureRouteToHost(mContext, mmscUrl, mTransactionSettings.proxyAddress)
return HttpUtils.httpConnection(
mContext, token,
mmscUrl,
pdu, HttpUtils.HTTP_POST_METHOD,
mTransactionSettings.isProxySet,
mTransactionSettings.proxyAddress,
mTransactionSettings.proxyPort)
}
}
private class NotifyRespTask internal constructor(context: Context, ind: NotificationInd, settings: TransactionSettings) : CommonAsyncTask(context, settings, ind) {
private val context = WeakReference<Context>(context)
override fun doInBackground(vararg params: Void): Void? {
// Create the M-NotifyResp.ind
var notifyRespInd: NotifyRespInd? = null
try {
notifyRespInd = NotifyRespInd(
PduHeaders.CURRENT_MMS_VERSION,
mNotificationInd.transactionId,
STATUS_RETRIEVED)
val mContext = this.context.get()
// Pack M-NotifyResp.ind and send it
if (com.android.mms.MmsConfig.getNotifyWapMMSC()) {
sendPdu(PduComposer(mContext, notifyRespInd).make(), mContentLocation)
} else {
sendPdu(PduComposer(mContext, notifyRespInd).make())
}
} catch (e: MmsException) {
Log.e(TAG, "error", e)
} catch (e: IOException) {
Log.e(TAG, "error", e)
}
return null
}
}
private class AcknowledgeIndTask internal constructor(context: Context, ind: NotificationInd, settings: TransactionSettings, private val mRetrieveConf: RetrieveConf) : CommonAsyncTask(context, settings, ind) {
private val context = WeakReference<Context>(context)
override fun doInBackground(vararg params: Void): Void? {
// Send M-Acknowledge.ind to MMSC if required.
// If the Transaction-ID isn't set in the M-Retrieve.conf, it means
// the MMS proxy-relay doesn't require an ACK.
val tranId = mRetrieveConf.transactionId
if (tranId != null) {
Log.v(TAG, "sending ACK to MMSC: " + mTransactionSettings.mmscUrl)
// Create M-Acknowledge.ind
var acknowledgeInd: com.google.android.mms.pdu_alt.AcknowledgeInd? = null
try {
acknowledgeInd = com.google.android.mms.pdu_alt.AcknowledgeInd(
PduHeaders.CURRENT_MMS_VERSION, tranId)
val mContext = context.get()
// insert the 'from' address per spec
val lineNumber = Utils.getMyPhoneNumber(mContext)
acknowledgeInd.from = EncodedStringValue(lineNumber)
// Pack M-Acknowledge.ind and send it
if (com.android.mms.MmsConfig.getNotifyWapMMSC()) {
sendPdu(PduComposer(mContext, acknowledgeInd).make(), mContentLocation)
} else {
sendPdu(PduComposer(mContext, acknowledgeInd).make())
}
} catch (e: InvalidHeaderValueException) {
Log.e(TAG, "error", e)
} catch (e: MmsException) {
Log.e(TAG, "error", e)
} catch (e: IOException) {
Log.e(TAG, "error", e)
}
}
return null
}
}
private fun getNotificationTask(context: Context, intent: Intent, response: ByteArray): List<CommonAsyncTask>? {
if (response.size == 0) {
Log.v(TAG, "MmsReceivedReceiver.sendNotification blank response")
return null
}
if (mmscInfoForReceptionAck == null) {
Log.v(TAG, "No MMSC information set, so no notification tasks will be able to complete")
return null
}
val pdu = PduParser(response, MmsConfig.Overridden(MmsConfig(context), null).supportMmsContentDisposition).parse()
if (pdu == null || pdu !is RetrieveConf) {
android.util.Log.e(TAG, "MmsReceivedReceiver.sendNotification failed to parse pdu")
return null
}
try {
val ind = getNotificationInd(context, intent)
val mmsc = mmscInfoForReceptionAck
val transactionSettings = TransactionSettings(mmsc!!.mmscUrl, mmsc.mmsProxy, mmsc.proxyPort)
val responseTasks = ArrayList<CommonAsyncTask>()
responseTasks.add(AcknowledgeIndTask(context, ind, transactionSettings, pdu))
responseTasks.add(NotifyRespTask(context, ind, transactionSettings))
return responseTasks
} catch (e: MmsException) {
Log.e(TAG, "error", e)
return null
}
}
class MmscInformation(internal var mmscUrl: String, internal var mmsProxy: String, internal var proxyPort: Int)
companion object {
private val TAG = "MmsReceivedReceiver"
val MMS_RECEIVED = "com.klinker.android.messaging.MMS_RECEIVED"
val EXTRA_FILE_PATH = "file_path"
val EXTRA_LOCATION_URL = "location_url"
val EXTRA_TRIGGER_PUSH = "trigger_push"
val EXTRA_URI = "notification_ind_uri"
private val LOCATION_SELECTION =
Telephony.Mms.MESSAGE_TYPE + "=? AND " + Telephony.Mms.CONTENT_LOCATION + " =?"
private val RECEIVE_NOTIFICATION_EXECUTOR = Executors.newSingleThreadExecutor()
@Throws(MmsException::class)
private fun getNotificationInd(context: Context, intent: Intent): NotificationInd {
return PduPersister.getPduPersister(context).load(intent.getParcelableExtra<Parcelable>(EXTRA_URI) as Uri) as NotificationInd
}
}
}

View file

@ -61,7 +61,6 @@ class NornMedia private constructor(context: Context, val mimeType: String) {
}
}
companion object {
fun from(context: Context, media: Media): NornMedia {

View file

@ -18,7 +18,9 @@ package xyz.johnny.norntalk.messages
import android.app.Activity
import android.app.PendingIntent
import android.content.*
import android.content.ContentResolver
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.os.Looper
@ -34,12 +36,14 @@ import com.android.mms.util.RateController
import com.google.android.mms.ContentType
import com.google.android.mms.InvalidHeaderValueException
import com.google.android.mms.MMSPart
import com.google.android.mms.MmsException
import com.google.android.mms.pdu_alt.*
import com.google.android.mms.smil.SmilHelper
import com.klinker.android.logger.Log
import com.klinker.android.send_message.*
import java.io.*
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import java.util.*
/**
@ -98,46 +102,6 @@ class NornTransaction constructor(private val context: Context) {
return true
}
/**
* Optional: define a [BroadcastReceiver] that will get started when Android notifies us that the SMS has
* been marked as "sent". If you do not define a receiver here, it will look for the .SMS_SENT receiver
* that was defined in the AndroidManifest, as discussed in the README.md.
*
* @param intent the receiver that you want to start when the message gets marked as sent.
*/
fun setExplicitBroadcastForSentSms(intent: Intent): NornTransaction {
explicitSentSmsReceiver = intent
return this
}
/**
* Optional: define a [BroadcastReceiver] that will get started when Android notifies us that the MMS has
* been marked as "sent". If you do not define a receiver here, it will look for the .MMS_SENT receiver
* that was defined in the AndroidManifest, as discussed in the README.md.
*
* @param intent the receiver that you want to start when the message gets marked as sent.
*/
fun setExplicitBroadcastForSentMms(intent: Intent): NornTransaction {
explicitSentMmsReceiver = intent
return this
}
/**
* Optional: define a [BroadcastReceiver] that will get started when Android notifies us that the SMS has
* been marked as "delivered". If you do not define a receiver here, it will look for the .SMS_DELIVERED
* receiver that was defined in the AndroidManifest, as discussed in the README.md.
*
*
* Providing a receiver here does not guarantee that it will ever get started. If the [Settings]
* object does not have delivery reports turned on, this receiver will never get called.
*
* @param intent the receiver that you want to start when the message gets marked as sent.
*/
fun setExplicitBroadcastForDeliveredSms(intent: Intent): NornTransaction {
explicitDeliveredSmsReceiver = intent
return this
}
private fun sendSmsMessage(message: NornMessage, insert: Boolean, raw: Boolean) {
// envoyer le message chiffré si la conversation est sécurisée
val body = message.messageBody(raw)
@ -273,12 +237,6 @@ class NornTransaction constructor(private val context: Context) {
sendMmsThroughSystem(context, message.subject, data, message.addresses, explicitSentMmsReceiver)
}
class MessageInfo {
var token: Long = 0
var location: Uri? = null
var bytes: ByteArray? = null
}
// splits text and adds split counter when applicable
private fun splitByLength(s: String, chunkSize: Int, counter: Boolean): Array<String?> {
val arraySize = Math.ceil(s.length.toDouble() / chunkSize).toInt()
@ -307,20 +265,6 @@ class NornTransaction constructor(private val context: Context) {
return returnArray
}
/**
* A method for checking whether or not a certain message will be sent as mms depending on its contents and the settings
*
* @param message is the message that you are checking against
* @return true if the message will be mms, otherwise false
*/
fun checkMMS(message: Message): Boolean {
return message.images.size != 0 ||
message.parts.size != 0 ||
settings.sendLongAsMms && Utils.getNumPages(settings, message.text) > settings.sendLongAsMmsAfter ||
message.addresses.size > 1 && settings.group ||
message.subject != null
}
companion object {
private val TAG = "NornTransaction"
@ -335,118 +279,6 @@ class NornTransaction constructor(private val context: Context) {
val NO_THREAD_ID: Long = 0
@Throws(MmsException::class)
fun getBytes(context: Context, saveMessage: Boolean, recipients: Array<String>,
parts: Array<MMSPart>?, subject: String?): MessageInfo {
val sendRequest = SendReq()
// create send request addresses
for (i in recipients.indices) {
val phoneNumbers = EncodedStringValue.extract(recipients[i])
if (phoneNumbers != null && phoneNumbers.size > 0) {
sendRequest.addTo(phoneNumbers[0])
}
}
if (subject != null) {
sendRequest.subject = EncodedStringValue(subject)
}
sendRequest.date = Calendar.getInstance().timeInMillis / 1000L
try {
sendRequest.from = EncodedStringValue(Utils.getMyPhoneNumber(context))
} catch (e: Exception) {
Log.e(TAG, "error getting from address", e)
}
val pduBody = PduBody()
// assign parts to the pdu body which contains sending data
var size: Long = 0
if (parts != null) {
for (i in parts.indices) {
val part = parts[i]
if (part != null) {
try {
val partPdu = PduPart()
partPdu.name = part.Name.toByteArray()
partPdu.contentType = part.MimeType.toByteArray()
if (part.MimeType.startsWith("text")) {
partPdu.charset = CharacterSets.UTF_8
}
// Set Content-Location.
partPdu.contentLocation = part.Name.toByteArray()
val index = part.Name.lastIndexOf(".")
val contentId = if (index == -1)
part.Name
else
part.Name.substring(0, index)
partPdu.contentId = contentId.toByteArray()
partPdu.data = part.Data
pduBody.addPart(partPdu)
size += (2 * part.Name.toByteArray().size + part.MimeType.toByteArray().size + part.Data.size + contentId.toByteArray().size).toLong()
} catch (e: Exception) {
}
}
}
}
val out = ByteArrayOutputStream()
SmilXmlSerializer.serialize(SmilHelper.createSmilDocument(pduBody), out)
val smilPart = PduPart()
smilPart.contentId = "smil".toByteArray()
smilPart.contentLocation = "smil.xml".toByteArray()
smilPart.contentType = ContentType.APP_SMIL.toByteArray()
smilPart.data = out.toByteArray()
pduBody.addPart(0, smilPart)
sendRequest.body = pduBody
Log.v(TAG, "setting message size to $size bytes")
sendRequest.messageSize = size
// add everything else that could be set
sendRequest.priority = PduHeaders.PRIORITY_NORMAL
sendRequest.deliveryReport = PduHeaders.VALUE_NO
sendRequest.expiry = (1000 * 60 * 60 * 24 * 7).toLong()
sendRequest.messageClass = PduHeaders.MESSAGE_CLASS_PERSONAL_STR.toByteArray()
sendRequest.readReport = PduHeaders.VALUE_NO
// create byte array which will actually be sent
val composer = PduComposer(context, sendRequest)
val bytesToSend: ByteArray
try {
bytesToSend = composer.make()
} catch (e: OutOfMemoryError) {
throw MmsException("Out of memory!")
}
val info = MessageInfo()
info.bytes = bytesToSend
try {
val query = context.contentResolver.query(info.location!!, arrayOf("thread_id"), null, null, null)
if (query != null && query.moveToFirst()) {
info.token = query.getLong(query.getColumnIndex("thread_id"))
query.close()
} else {
// just default sending token for what I had before
info.token = 4444L
}
} catch (e: Exception) {
Log.e(TAG, "exception thrown", e)
info.token = 4444L
}
return info
}
val DEFAULT_EXPIRY_TIME = (7 * 24 * 60 * 60).toLong()
val DEFAULT_PRIORITY = PduHeaders.PRIORITY_NORMAL
@ -494,7 +326,6 @@ class NornTransaction constructor(private val context: Context) {
contentUri, null, configOverrides, pendingIntent)
} else {
Log.e(TAG, "Error writing sending Mms")
println("aaajoai")
pendingIntent.send(SmsManager.MMS_ERROR_IO_ERROR)
}
@ -581,57 +412,6 @@ class NornTransaction constructor(private val context: Context) {
return part.data.size
}
// create the image part to be stored in database
@Throws(Exception::class)
private fun createPartImage(context: Context, id: String, imageBytes: ByteArray, mimeType: String): Uri {
val mmsPartValue = ContentValues()
mmsPartValue.put("mid", id)
mmsPartValue.put("ct", mimeType)
mmsPartValue.put("cid", "<" + System.currentTimeMillis() + ">")
val partUri = Uri.parse("content://mms/$id/part")
val res = context.contentResolver.insert(partUri, mmsPartValue)
// Add data to part
val os = context.contentResolver.openOutputStream(res!!)
val `is` = ByteArrayInputStream(imageBytes)
val buffer = ByteArray(256)
var len = `is`.read(buffer)
while (len != -1) {
os!!.write(buffer, 0, len)
len = `is`.read(buffer)
}
os!!.close()
`is`.close()
return res
}
// create the text part to be stored in database
@Throws(Exception::class)
private fun createPartText(context: Context, id: String, text: String): Uri? {
val mmsPartValue = ContentValues()
mmsPartValue.put("mid", id)
mmsPartValue.put("ct", "text/plain")
mmsPartValue.put("cid", "<" + System.currentTimeMillis() + ">")
mmsPartValue.put("text", text)
val partUri = Uri.parse("content://mms/$id/part")
return context.contentResolver.insert(partUri, mmsPartValue)
}
// add address to the request
@Throws(Exception::class)
private fun createAddr(context: Context, id: String, addr: String): Uri? {
val addrValues = ContentValues()
addrValues.put("address", addr)
addrValues.put("charset", "106")
addrValues.put("type", 151) // TO
val addrUri = Uri.parse("content://mms/$id/addr")
return context.contentResolver.insert(addrUri, addrValues)
}
}
}

View file

@ -47,7 +47,8 @@ class ComposeView: View {
fun sendMessage(view: View) {
val text = composeInput.text.toString()
this.composeInput.text.clear()
this.sendMessage(text, this.medias)
this.sendMessage(text, this.medias.toTypedArray().copyOf())
this.medias.removeAll { true }
}
fun pickPicture() {
@ -75,7 +76,7 @@ class ComposeView: View {
* @param text Contenu du message
* @param medias Documents à envoyer
*/
abstract fun sendMessage(text: String, medias: ArrayList<NornMedia>)
abstract fun sendMessage(text: String, medias: Array<NornMedia>)
}