diff --git a/README.md b/README.md index bef714d..43ea04b 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,8 @@ Note that upon import or wipe, message apps present on the system may not immedi SMS Import / Export tries to preserve as much data and metadata as possible upon import. Android includes a `sub_id` ([Subscription ID](https://developer.android.com/training/articles/user-data-ids#accounts)) field in both [SMS](https://developer.android.com/reference/android/provider/Telephony.TextBasedSmsColumns) and [MMS](https://developer.android.com/reference/android/provider/Telephony.BaseMmsColumns#SUBSCRIPTION_ID) message metadata. Earlier versions of the app included these `sub_id`s when importing, but this can cause messages to disappear on Android 14 ([issue #128](https://github.com/tmo1/sms-ie/issues/128), [Reddit](https://old.reddit.com/r/android_beta/comments/15mzaij/sms_backup_and_restore_issues/)), so the current default is to set all `sub_id`s to `-1` upon import ([negative values indicate that "the sub id cannot be determined"](https://developer.android.com/reference/android/provider/Telephony.TextBasedSmsColumns#SUBSCRIPTION_ID)). The old behavior is still available via a settings toggle. +Additionally, some MMS part metadata apparently contain a `sub_id` field as well (despite the absence of any mention of this in [the API documentation](https://developer.android.com/reference/android/provider/Telephony.Mms.Part)), and [attempting to import these `sub_id`s can cause the app to crash](https://github.com/tmo1/sms-ie/issues/142). These `sub_id`s are currently handled the same way as the ones in the SMS and MMS metadata. + ### Deduplication SMS Import / Export can attempt to deduplicate messages upon import. If this feature is enabled in the app's settings, the app will check all new messages against the existing message database (including those messages already inserted earlier in the import process) and ignore those it considers to be duplicates of ones already present. This feature is currently considered experimental. diff --git a/app/src/main/java/com/github/tmo1/sms_ie/ImportExportMessages.kt b/app/src/main/java/com/github/tmo1/sms_ie/ImportExportMessages.kt index d158841..ac65099 100644 --- a/app/src/main/java/com/github/tmo1/sms_ie/ImportExportMessages.kt +++ b/app/src/main/java/com/github/tmo1/sms_ie/ImportExportMessages.kt @@ -412,8 +412,7 @@ suspend fun importMessages( if (key in smsColumns) messageMetadata.put( key, messageJSON.getString(key) ) - } - /* If we don't yet have a 'thread_id' (i.e., the message has a new + }/* If we don't yet have a 'thread_id' (i.e., the message has a new 'thread_id' that we haven't yet encountered and so isn't yet in 'threadIdMap'), then we need to get a new 'thread_id' and record the mapping between the old and new ones in 'threadIdMap' @@ -526,8 +525,7 @@ suspend fun importMessages( addresses.add(address) } } - } - /* If we don't yet have a thread_id (i.e., the message has a new + }/* If we don't yet have a thread_id (i.e., the message has a new thread_id that we haven't yet encountered and so isn't yet in threadIdMap), then we need to get a new thread_id and record the mapping between the old and new ones in threadIdMap @@ -562,8 +560,7 @@ suspend fun importMessages( addresses.forEach { address -> address.put( Telephony.Mms.Addr.MSG_ID, messageId - ) - /*Log.v( + )/*Log.v( LOG_TAG, "Trying to insert MMS address - metadata:" + address.toString() )*/ @@ -572,8 +569,7 @@ suspend fun importMessages( addressUri, address ) if (insertAddressUri == null) Log.e( - LOG_TAG, - "MMS address insert failed!" + LOG_TAG, "MMS address insert failed!" ) else Log.d(LOG_TAG, "MMS address insert succeeded") } @@ -589,6 +585,15 @@ suspend fun importMessages( partKey, messagePart.getString(partKey) ) } + // Some MMS part metadata contain sub_ids, and attempting to import them can cause a FileNotFoundException: No entry for content + // when subsequently trying to write the part's binary data. + // See: https://github.com/tmo1/sms-ie/issues/142 + if (!prefs.getBoolean( + "import_sub_ids", false + ) && part.containsKey("sub_id") + ) { + part.put("sub_id", "-1") + } val insertPartUri = appContext.contentResolver.insert( partUri, part