diff --git a/Gemfile b/Gemfile new file mode 100644 index 000000000..bc1d46abc --- /dev/null +++ b/Gemfile @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +source "https://rubygems.org" + +gem "fastlane" +gem "screengrab" diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 000000000..22cbee257 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,221 @@ +GEM + remote: https://rubygems.org/ + specs: + CFPropertyList (3.0.5) + rexml + addressable (2.8.0) + public_suffix (>= 2.0.2, < 5.0) + artifactory (3.0.15) + atomos (0.1.3) + aws-eventstream (1.2.0) + aws-partitions (1.566.0) + aws-sdk-core (3.130.0) + aws-eventstream (~> 1, >= 1.0.2) + aws-partitions (~> 1, >= 1.525.0) + aws-sigv4 (~> 1.1) + jmespath (~> 1.0) + aws-sdk-kms (1.55.0) + aws-sdk-core (~> 3, >= 3.127.0) + aws-sigv4 (~> 1.1) + aws-sdk-s3 (1.113.0) + aws-sdk-core (~> 3, >= 3.127.0) + aws-sdk-kms (~> 1) + aws-sigv4 (~> 1.4) + aws-sigv4 (1.4.0) + aws-eventstream (~> 1, >= 1.0.2) + babosa (1.0.4) + claide (1.1.0) + colored (1.2) + colored2 (3.1.2) + commander (4.6.0) + highline (~> 2.0.0) + declarative (0.0.20) + digest-crc (0.6.4) + rake (>= 12.0.0, < 14.0.0) + domain_name (0.5.20190701) + unf (>= 0.0.5, < 1.0.0) + dotenv (2.7.6) + emoji_regex (3.2.3) + excon (0.91.0) + faraday (1.10.0) + faraday-em_http (~> 1.0) + faraday-em_synchrony (~> 1.0) + faraday-excon (~> 1.1) + faraday-httpclient (~> 1.0) + faraday-multipart (~> 1.0) + faraday-net_http (~> 1.0) + faraday-net_http_persistent (~> 1.0) + faraday-patron (~> 1.0) + faraday-rack (~> 1.0) + faraday-retry (~> 1.0) + ruby2_keywords (>= 0.0.4) + faraday-cookie_jar (0.0.7) + faraday (>= 0.8.0) + http-cookie (~> 1.0.0) + faraday-em_http (1.0.0) + faraday-em_synchrony (1.0.0) + faraday-excon (1.1.0) + faraday-httpclient (1.0.1) + faraday-multipart (1.0.3) + multipart-post (>= 1.2, < 3) + faraday-net_http (1.0.1) + faraday-net_http_persistent (1.2.0) + faraday-patron (1.0.0) + faraday-rack (1.0.0) + faraday-retry (1.0.3) + faraday_middleware (1.2.0) + faraday (~> 1.0) + fastimage (2.2.6) + fastlane (2.204.3) + CFPropertyList (>= 2.3, < 4.0.0) + addressable (>= 2.8, < 3.0.0) + artifactory (~> 3.0) + aws-sdk-s3 (~> 1.0) + babosa (>= 1.0.3, < 2.0.0) + bundler (>= 1.12.0, < 3.0.0) + colored + commander (~> 4.6) + dotenv (>= 2.1.1, < 3.0.0) + emoji_regex (>= 0.1, < 4.0) + excon (>= 0.71.0, < 1.0.0) + faraday (~> 1.0) + faraday-cookie_jar (~> 0.0.6) + faraday_middleware (~> 1.0) + fastimage (>= 2.1.0, < 3.0.0) + gh_inspector (>= 1.1.2, < 2.0.0) + google-apis-androidpublisher_v3 (~> 0.3) + google-apis-playcustomapp_v1 (~> 0.1) + google-cloud-storage (~> 1.31) + highline (~> 2.0) + json (< 3.0.0) + jwt (>= 2.1.0, < 3) + mini_magick (>= 4.9.4, < 5.0.0) + multipart-post (~> 2.0.0) + naturally (~> 2.2) + optparse (~> 0.1.1) + plist (>= 3.1.0, < 4.0.0) + rubyzip (>= 2.0.0, < 3.0.0) + security (= 0.1.3) + simctl (~> 1.6.3) + terminal-notifier (>= 2.0.0, < 3.0.0) + terminal-table (>= 1.4.5, < 2.0.0) + tty-screen (>= 0.6.3, < 1.0.0) + tty-spinner (>= 0.8.0, < 1.0.0) + word_wrap (~> 1.0.0) + xcodeproj (>= 1.13.0, < 2.0.0) + xcpretty (~> 0.3.0) + xcpretty-travis-formatter (>= 0.0.3) + gh_inspector (1.1.3) + google-apis-androidpublisher_v3 (0.16.0) + google-apis-core (>= 0.4, < 2.a) + google-apis-core (0.4.2) + addressable (~> 2.5, >= 2.5.1) + googleauth (>= 0.16.2, < 2.a) + httpclient (>= 2.8.1, < 3.a) + mini_mime (~> 1.0) + representable (~> 3.0) + retriable (>= 2.0, < 4.a) + rexml + webrick + google-apis-iamcredentials_v1 (0.10.0) + google-apis-core (>= 0.4, < 2.a) + google-apis-playcustomapp_v1 (0.7.0) + google-apis-core (>= 0.4, < 2.a) + google-apis-storage_v1 (0.11.0) + google-apis-core (>= 0.4, < 2.a) + google-cloud-core (1.6.0) + google-cloud-env (~> 1.0) + google-cloud-errors (~> 1.0) + google-cloud-env (1.5.0) + faraday (>= 0.17.3, < 2.0) + google-cloud-errors (1.2.0) + google-cloud-storage (1.36.1) + addressable (~> 2.8) + digest-crc (~> 0.4) + google-apis-iamcredentials_v1 (~> 0.1) + google-apis-storage_v1 (~> 0.1) + google-cloud-core (~> 1.6) + googleauth (>= 0.16.2, < 2.a) + mini_mime (~> 1.0) + googleauth (1.1.2) + faraday (>= 0.17.3, < 3.a) + jwt (>= 1.4, < 3.0) + memoist (~> 0.16) + multi_json (~> 1.11) + os (>= 0.9, < 2.0) + signet (>= 0.16, < 2.a) + highline (2.0.3) + http-cookie (1.0.4) + domain_name (~> 0.5) + httpclient (2.8.3) + jmespath (1.6.1) + json (2.6.1) + jwt (2.3.0) + memoist (0.16.2) + mini_magick (4.11.0) + mini_mime (1.1.2) + multi_json (1.15.0) + multipart-post (2.0.0) + nanaimo (0.3.0) + naturally (2.2.1) + optparse (0.1.1) + os (1.1.4) + plist (3.6.0) + public_suffix (4.0.6) + rake (13.0.6) + representable (3.1.1) + declarative (< 0.1.0) + trailblazer-option (>= 0.1.1, < 0.2.0) + uber (< 0.2.0) + retriable (3.1.2) + rexml (3.2.5) + rouge (2.0.7) + ruby2_keywords (0.0.5) + rubyzip (2.3.2) + screengrab (1.0.0) + fastlane (>= 2.0.0, < 3.0.0) + security (0.1.3) + signet (0.16.1) + addressable (~> 2.8) + faraday (>= 0.17.5, < 3.0) + jwt (>= 1.5, < 3.0) + multi_json (~> 1.10) + simctl (1.6.8) + CFPropertyList + naturally + terminal-notifier (2.0.0) + terminal-table (1.8.0) + unicode-display_width (~> 1.1, >= 1.1.1) + trailblazer-option (0.1.2) + tty-cursor (0.7.1) + tty-screen (0.8.1) + tty-spinner (0.9.3) + tty-cursor (~> 0.7) + uber (0.1.0) + unf (0.1.4) + unf_ext + unf_ext (0.0.8) + unicode-display_width (1.8.0) + webrick (1.7.0) + word_wrap (1.0.0) + xcodeproj (1.21.0) + CFPropertyList (>= 2.3.3, < 4.0) + atomos (~> 0.1.3) + claide (>= 1.0.2, < 2.0) + colored2 (~> 3.1) + nanaimo (~> 0.3.0) + rexml (~> 3.2.4) + xcpretty (0.3.0) + rouge (~> 2.0.7) + xcpretty-travis-formatter (1.0.1) + xcpretty (~> 0.2, >= 0.0.7) + +PLATFORMS + x86_64-linux + +DEPENDENCIES + fastlane + screengrab + +BUNDLED WITH + 2.2.5 diff --git a/build.gradle b/build.gradle index 0873cc2f3..53eeb56ee 100644 --- a/build.gradle +++ b/build.gradle @@ -121,12 +121,12 @@ android { targetSdkVersion 29 versionCode 42024 + grgit.tag.list().size() versionName grgit.describe(tags: true, always: true) - archivesBaseName += "-$versionName" applicationId "eu.siacs.conversations" resValue "string", "applicationId", applicationId def appName = "Conversations" resValue "string", "app_name", appName buildConfigField "String", "APP_NAME", "\"$appName\""; + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } diff --git a/fastlane/Appfile b/fastlane/Appfile new file mode 100644 index 000000000..03f2a0370 --- /dev/null +++ b/fastlane/Appfile @@ -0,0 +1,2 @@ +json_key_file("") # Path to the json secret file - Follow https://docs.fastlane.tools/actions/supply/#setup to get one +package_name("com.cheogram.android") # e.g. com.krausefx.app diff --git a/fastlane/Fastfile b/fastlane/Fastfile new file mode 100644 index 000000000..ec1fe5a71 --- /dev/null +++ b/fastlane/Fastfile @@ -0,0 +1,38 @@ +# This file contains the fastlane.tools configuration +# You can find the documentation at https://docs.fastlane.tools +# +# For a list of all available actions, check out +# +# https://docs.fastlane.tools/actions +# +# For a list of all available plugins, check out +# +# https://docs.fastlane.tools/plugins/available-plugins +# + +# Uncomment the line if you want fastlane to automatically update itself +# update_fastlane + +default_platform(:android) + +platform :android do + desc "Build debug and test APK for screenshots" + lane :build_for_screengrab do + build_android_app( + task: 'assemble', + flavor: 'CheogramFree', + build_type: 'Debug' + ) + build_android_app( + task: 'assemble', + flavor: 'CheogramFree', + build_type: 'DebugAndroidTest' + ) + end + + desc "Build and take screenshots" + lane :build_and_screengrab do + build_for_screengrab + capture_android_screenshots + end +end diff --git a/fastlane/Screengrabfile b/fastlane/Screengrabfile new file mode 100644 index 000000000..1459e884a --- /dev/null +++ b/fastlane/Screengrabfile @@ -0,0 +1,5 @@ +locales ['en-US'] +clear_previous_screenshots true +tests_apk_path 'build/outputs/apk/androidTest/cheogramFree/debug/Conversations-cheogram-free-debug-androidTest.apk' +app_apk_path 'build/outputs/apk/cheogramFree/debug/Conversations-cheogram-free-debug.apk' +test_instrumentation_runner 'androidx.test.runner.AndroidJUnitRunner' \ No newline at end of file diff --git a/fastlane/metadata/android/en_US/full_description.txt b/fastlane/metadata/android/en_US/full_description.txt index e3b806b02..1a7c76c2c 100644 --- a/fastlane/metadata/android/en_US/full_description.txt +++ b/fastlane/metadata/android/en_US/full_description.txt @@ -1,39 +1,16 @@ -Easy to use, reliable, battery friendly. With built-in support for images, group chats and e2e encryption. +The Cheogram Android app allows you to join a worldwide communication network. It especially focuses on features useful to users who want to contact those on other networks as well, such as SMS-enabled phone numbers. -Design principles: +Unique Features: -* Be as beautiful and easy to use as possible without sacrificing security or privacy -* Rely on existing, well established protocols -* Do not require a Google Account or specifically Google Cloud Messaging (GCM) -* Require as few permissions as possible - -Features: - -* End-to-end encryption with either OMEMO or OpenPGP -* Sending and receiving images -* Encrypted audio and video calls (DTLS-SRTP) -* Intuitive UI that follows Android Design guidelines -* Pictures / Avatars for your Contacts -* Syncs with desktop client -* Conferences (with support for bookmarks) +* Messages with both media and text, including animated media +* Unobtrusive display of subject lines, where present +* Links to known contacts are shown with their name +* Integrates with gateways add contact flows +* When using a gateway to the phone network, integrate with the native Android Phone app * Address book integration -* Multiple accounts / unified inbox -* Very low impact on battery life -Conversations makes it very easy to create an account on the conversations.im server. Using that server comes with an annual fee of 8 Euro after a 6 month trial period. However Conversations will work with any other XMPP server as well. A lot of XMPP servers are run by volunteers and are free of charge. +Where to get service: -XMPP Features: +Cheogram Android requires you have an account with a Jabber service. You can run your own service, or use one provided by someone else, for example: https://snikket.org/hosting/ -Conversations works with every XMPP server out there. However XMPP is an extensible protocol. These extensions are standardized as well in so called XEP’s. Conversations supports a couple of those to make the overall user experience better. There is a chance that your current XMPP server does not support these extensions. Therefore to get the most out of Conversations you should consider either switching to an XMPP server that does or - even better - run your own XMPP server for you and your friends. - -These XEPs are - as of now: - -* XEP-0065: SOCKS5 Bytestreams (or mod_proxy65). Will be used to transfer files if both parties are behind a firewall (NAT). -* XEP-0163: Personal Eventing Protocol for avatars -* XEP-0191: Blocking command lets you blacklist spammers or block contacts without removing them from your roster. -* XEP-0198: Stream Management allows XMPP to survive small network outages and changes of the underlying TCP connection. -* XEP-0280: Message Carbons which automatically syncs the messages you send to your desktop client and thus allows you to switch seamlessly from your mobile client to your desktop client and back within one conversation. -* XEP-0237: Roster Versioning mainly to save bandwidth on poor mobile connections -* XEP-0313: Message Archive Management synchronize message history with the server. Catch up with messages that were sent while Conversations was offline. -* XEP-0352: Client State Indication lets the server know whether or not Conversations is in the background. Allows the server to save bandwidth by withholding unimportant packages. -* XEP-0363: HTTP File Upload allows you to share files in conferences and with offline contacts. Requires an additional component on your server. +Art in screenshots is from https://www.peppercarrot.com by David Revoy, CC-BY. Artwork has been modified to crop out sections for avatars and photos, and in some cases add transparency. Use of this artwork does not imply endoresement of this project by the artist. diff --git a/fastlane/metadata/android/en_US/images/phoneScreenshots/conversation.png b/fastlane/metadata/android/en_US/images/phoneScreenshots/conversation.png index eb74ffb5a..860a7c132 100644 Binary files a/fastlane/metadata/android/en_US/images/phoneScreenshots/conversation.png and b/fastlane/metadata/android/en_US/images/phoneScreenshots/conversation.png differ diff --git a/fastlane/metadata/android/en_US/images/phoneScreenshots/startConversation.png b/fastlane/metadata/android/en_US/images/phoneScreenshots/startConversation.png new file mode 100644 index 000000000..762cb978c Binary files /dev/null and b/fastlane/metadata/android/en_US/images/phoneScreenshots/startConversation.png differ diff --git a/fastlane/metadata/android/en_US/images/phoneScreenshots/startConversationOptions.png b/fastlane/metadata/android/en_US/images/phoneScreenshots/startConversationOptions.png new file mode 100644 index 000000000..0f3a7a4d4 Binary files /dev/null and b/fastlane/metadata/android/en_US/images/phoneScreenshots/startConversationOptions.png differ diff --git a/src/androidTest/java/com/cheogram/android/test/ScreenshotTest.java b/src/androidTest/java/com/cheogram/android/test/ScreenshotTest.java new file mode 100644 index 000000000..ce0fd62ad --- /dev/null +++ b/src/androidTest/java/com/cheogram/android/test/ScreenshotTest.java @@ -0,0 +1,169 @@ +package com.cheogram.android.test; + +import java.util.concurrent.TimeoutException; +import java.lang.Thread; +import java.util.Arrays; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +import android.app.Activity; +import android.content.Intent; +import android.graphics.Bitmap; +import android.net.Uri; +import android.os.Bundle; +import android.util.Log; + +import androidx.test.InstrumentationRegistry; +import androidx.test.core.app.ActivityScenario; +import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.rules.ActivityScenarioRule; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.rule.ServiceTestRule; +import static androidx.test.espresso.Espresso.onView; +import static androidx.test.espresso.action.ViewActions.click; +import static androidx.test.espresso.matcher.ViewMatchers.withId; + +import tools.fastlane.screengrab.Screengrab; +import tools.fastlane.screengrab.cleanstatusbar.CleanStatusBar; +import tools.fastlane.screengrab.locale.LocaleTestRule; + +import eu.siacs.conversations.entities.Account; +import eu.siacs.conversations.entities.Contact; +import eu.siacs.conversations.entities.Conversation; +import eu.siacs.conversations.entities.Message; +import eu.siacs.conversations.entities.Presence; +import eu.siacs.conversations.entities.ServiceDiscoveryResult; +import eu.siacs.conversations.entities.TransferablePlaceholder; +import eu.siacs.conversations.persistance.FileBackend; +import eu.siacs.conversations.services.XmppConnectionService.XmppConnectionBinder; +import eu.siacs.conversations.services.XmppConnectionService; +import eu.siacs.conversations.test.R; +import eu.siacs.conversations.ui.ConversationsActivity; +import eu.siacs.conversations.ui.StartConversationActivity; +import eu.siacs.conversations.xml.Element; +import eu.siacs.conversations.xmpp.Jid; +import eu.siacs.conversations.xmpp.pep.Avatar; +import eu.siacs.conversations.xmpp.stanzas.IqPacket; + +@RunWith(AndroidJUnit4.class) +public class ScreenshotTest { + + static String pkg = InstrumentationRegistry.getInstrumentation().getContext().getPackageName(); + static XmppConnectionService xmppConnectionService; + static Account account; + + @ClassRule + public static final LocaleTestRule localeTestRule = new LocaleTestRule(); + + @ClassRule + public static final ServiceTestRule xmppServiceRule = new ServiceTestRule(); + + @BeforeClass + public static void setup() throws TimeoutException { + CleanStatusBar.enableWithDefaults(); + + Intent intent = new Intent(ApplicationProvider.getApplicationContext(), XmppConnectionService.class); + intent.setAction("ui"); + xmppConnectionService = ((XmppConnectionBinder) xmppServiceRule.bindService(intent)).getService(); + account = xmppConnectionService.findAccountByJid(Jid.of("carrot@chaosah.hereva")); + if (account == null) { + account = new Account( + Jid.of("carrot@chaosah.hereva"), + "orangeandfurry" + ); + xmppConnectionService.createAccount(account); + } + + Uri avatarUri = Uri.parse("android.resource://" + pkg + "/" + String.valueOf(R.drawable.carrot)); + final Avatar avatar = xmppConnectionService.getFileBackend().getPepAvatar(avatarUri, 192, Bitmap.CompressFormat.WEBP); + xmppConnectionService.getFileBackend().save(avatar); + account.setAvatar(avatar.getFilename()); + + Contact cheogram = account.getRoster().getContact(Jid.of("cheogram.com")); + cheogram.setOption(Contact.Options.IN_ROSTER); + cheogram.setPhotoUri("android.resource://" + pkg + "/" + String.valueOf(R.drawable.cheogram)); + Presence cheogramPresence = Presence.parse(null, null, ""); + IqPacket discoPacket = new IqPacket(IqPacket.TYPE.RESULT); + Element query = discoPacket.addChild("query", "http://jabber.org/protocol/disco#info"); + Element identity = query.addChild("identity"); + identity.setAttribute("category", "gateway"); + identity.setAttribute("type", "pstn"); + cheogramPresence.setServiceDiscoveryResult(new ServiceDiscoveryResult(discoPacket)); + cheogram.updatePresence("gw", cheogramPresence); + } + + @AfterClass + public static void teardown() { + CleanStatusBar.disable(); + } + + @Test + public void testConversation() throws FileBackend.FileCopyException, InterruptedException { + Conversation conversation = xmppConnectionService.findOrCreateConversation(account, Jid.of("+15550737737@cheogram.com"), false, false); + conversation.getContact().setOption(Contact.Options.IN_ROSTER); + conversation.getContact().setSystemName("Pepper"); + conversation.getContact().setPhotoUri("android.resource://" + pkg + "/" + String.valueOf(R.drawable.pepper)); + + Message voicemail = new Message(conversation, "", 0, Message.STATUS_RECEIVED); + voicemail.setOob("https://example.com/thing.mp3"); + voicemail.setFileParams(new Message.FileParams("https://example.com/thing.mp3|5000|0|0|10000")); + voicemail.setType(Message.TYPE_FILE); + voicemail.setSubject("Voicemail Recording"); + + Message transcript = new Message(conversation, "Where are you?", 0, Message.STATUS_RECEIVED); + transcript.setSubject("Voicemail Transcription"); + + Message picture = new Message(conversation, "", 0, Message.STATUS_SEND_RECEIVED); + picture.setOob("https://example.com/thing.webp"); + picture.setType(Message.TYPE_FILE); + xmppConnectionService.getFileBackend().copyFileToPrivateStorage( + picture, + Uri.parse("android.resource://" + pkg + "/" + String.valueOf(R.drawable.komona)), + "image/webp" + ); + xmppConnectionService.getFileBackend().updateFileParams(picture); + + conversation.addAll(0, Arrays.asList( + voicemail, + transcript, + new Message(conversation, "Meow", 0, Message.STATUS_SEND_RECEIVED), + picture, + new Message(conversation, "👍", 0, Message.STATUS_RECEIVED) + )); + + ActivityScenario scenario = ActivityScenario.launch(ConversationsActivity.class); + scenario.onActivity((Activity activity) -> { + ((ConversationsActivity) activity).switchToConversation(conversation); + }); + InstrumentationRegistry.getInstrumentation().waitForIdleSync(); + Thread.sleep(100); // ImageView not paited yet after waitForIdleSync + Screengrab.screenshot("conversation"); + } + + @Test + public void testStartConversation() throws InterruptedException { + ActivityScenario scenario = ActivityScenario.launch(StartConversationActivity.class); + InstrumentationRegistry.getInstrumentation().waitForIdleSync(); + Thread.sleep(100); // ImageView not paited yet after waitForIdleSync + Screengrab.screenshot("startConversation"); + } + + @Test + public void testAddContact() throws InterruptedException { + ActivityScenario scenario = ActivityScenario.launch(StartConversationActivity.class); + onView(withId(eu.siacs.conversations.R.id.speed_dial)).perform(click()); + Screengrab.screenshot("startConversationOptions"); + + // Not actually online, so can't screenshot the gateway selector yet + /*onView(withId(eu.siacs.conversations.R.id.create_contact)).perform(click()); + InstrumentationRegistry.getInstrumentation().waitForIdleSync(); + Thread.sleep(10000); // ImageView not paited yet after waitForIdleSync + Screengrab.screenshot("addContact");*/ + } +} diff --git a/src/androidTest/res/drawable/carrot.webp b/src/androidTest/res/drawable/carrot.webp new file mode 100644 index 000000000..cf0cd1288 Binary files /dev/null and b/src/androidTest/res/drawable/carrot.webp differ diff --git a/src/androidTest/res/drawable/cheogram.png b/src/androidTest/res/drawable/cheogram.png new file mode 100644 index 000000000..ff4b5cf9c Binary files /dev/null and b/src/androidTest/res/drawable/cheogram.png differ diff --git a/src/androidTest/res/drawable/komona.webp b/src/androidTest/res/drawable/komona.webp new file mode 100644 index 000000000..19cb20d1d Binary files /dev/null and b/src/androidTest/res/drawable/komona.webp differ diff --git a/src/androidTest/res/drawable/pepper.webp b/src/androidTest/res/drawable/pepper.webp new file mode 100644 index 000000000..fd3d822f0 Binary files /dev/null and b/src/androidTest/res/drawable/pepper.webp differ diff --git a/src/main/java/eu/siacs/conversations/utils/MimeUtils.java b/src/main/java/eu/siacs/conversations/utils/MimeUtils.java index 90f27f65f..30ab1db48 100644 --- a/src/main/java/eu/siacs/conversations/utils/MimeUtils.java +++ b/src/main/java/eu/siacs/conversations/utils/MimeUtils.java @@ -528,15 +528,12 @@ public final class MimeUtils { public static String guessMimeTypeFromUriAndMime(final Context context, final Uri uri, final String mime) { Log.d(Config.LOGTAG, "guessMimeTypeFromUriAndMime " + uri + " and mime=" + mime); - if (mime == null || mime.equals("application/octet-stream")) { - final String guess = guessMimeTypeFromUri(context, uri); - if (guess != null) { - return guess; - } else { - return mime; - } + final String guess = guessMimeTypeFromUri(context, uri); + if (guess != null) { + return guess; + } else { + return mime; } - return guessMimeTypeFromUri(context, uri); } public static String guessMimeTypeFromUri(Context context, Uri uri) {