I am building an android app in Java for personal use, that would make use of the Dropbox api.
When I run a basic local unit test, I can make the simple call, that returns my username with the dropbox token. If however I try to run the same code in an Android emulator, I get the following exception:
java.lang.Class<com.android.org.conscrypt.OpenSSLSocketFactoryImpl> is not accessible from java.lang.Class<javax.net.ssl.SSLSocketFactory>
Here is the activity code in Android
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding;
private Data data;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
binding.button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
testMe(view);
}
});
}
private void testMe(View v){
String clientId = String.format("%s/%s", BuildConfig.APPLICATION_ID, BuildConfig.VERSION_NAME);
DbxRequestConfig config = new DbxRequestConfig(clientId);
DbxClientV2 client = new DbxClientV2(config,BuildConfig.dropboxToken);
String s="";
try {
s = client.users().getCurrentAccount().toString();
} catch (DbxException e) {
e.printStackTrace();
}
}
}
I have a very simple activity with one button which after I click, it is supposed to get my username from Dropbox, but when I click it, it throws the exception described above and crashes.
My build.gradle is:
plugins {
id 'com.android.application'
}
android {
namespace 'com.daresunny.librebudget'
compileSdk 34
defaultConfig {
applicationId "com.daresunny.librebudget"
android.buildFeatures.buildConfig true
minSdk 28
targetSdk 34
versionCode 1
versionName "1.0"
Properties localProperties = getLocalProperties()
String dropboxKey = localProperties['DROPBOX_APP_KEY']
String secretToken = localProperties['DROPBOX_APP_TOKEN']
if (dropboxKey == null) {
dropboxKey = "missingApiKey"
logger.warn("No value provided for DROPBOX_APP_KEY. Specify a value in a examples/android/local.properties file. You can register for one at https://developers.dropbox.com/")
}
buildConfigField "String","dropboxAPIKey", "\"${dropboxKey}\""
buildConfigField "String","dropboxToken", "\"${secretToken}\""
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
buildFeatures {
viewBinding true
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'org.bouncycastle:bcpkix-jdk15on:1.67'
implementation 'com.google.android.material:material:1.11.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'com.dropbox.core:dropbox-android-sdk:6.0.0'
testImplementation 'junit:junit:4.13.2'
testImplementation 'org.mockito:mockito-core:5.4.0'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
}
def getLocalProperties() {
Properties props = new Properties()
if (file('local.properties').exists()) {
props.load(new FileInputStream(file('local.properties')))
}
return props
}
My Android Manifest is:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<application
android:requestLegacyExternalStorage="true"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Librebudget"
tools:targetApi="28">
<activity
android:name=".gui.MainActivity"
android:exported="true"
android:label="@string/title_activity_main"
android:theme="@style/Theme.Librebudget.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
And If it is of any relevance, I am using Android studio on Linux.
I would be grateful if anyone knows what can be causing this exception. It seems to be somehow related to the Android emulator, since the same test works perfectly fine outside of the android environment.
Edit:
It seems to me that it has something to do with the https requests that the dropbox api relies on. I get the same exception, when I try to just ping Wikipedia as shown in the example:
https://developer.android.com/privacy-and-security/security-ssl#java
The exception gets thrown by the method SocketFactor.getDefault(). Has it something to do with an SSL api, that is just not present on the emulator? If so can it be changed to an alternative one, at least while I test my application?