Skip to content

Commit 9710d76

Browse files
committed
Fix Server Picker tests, downgrade Hybrid Apps to API 34 and fix Edge to Edge issues in native apps.
1 parent ebe43e3 commit 9710d76

File tree

8 files changed

+86
-37
lines changed

8 files changed

+86
-37
lines changed

hybrid/HybridSampleApps/AccountEditor/build.gradle.kts

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@ dependencies {
1313
android {
1414
namespace = "com.salesforce.samples.accounteditor"
1515

16-
compileSdk = 35
16+
compileSdk = 34
1717

1818
defaultConfig {
19-
targetSdk = 35
19+
targetSdk = 34
2020
minSdk = 26
2121
}
2222

hybrid/HybridSampleApps/MobileSyncExplorerHybrid/build.gradle.kts

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@ dependencies {
1313
android {
1414
namespace = "com.salesforce.samples.mobilesyncexplorerhybrid"
1515

16-
compileSdk = 35
16+
compileSdk = 34
1717

1818
defaultConfig {
19-
targetSdk = 35
19+
targetSdk = 34
2020
minSdk = 26
2121
}
2222

libs/SalesforceSDK/src/com/salesforce/androidsdk/ui/ServerPickerActivity.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,9 @@ public void onAuthConfigFetched() {
300300
* The only other way to do this is with the NO_HISTORY flag on the custom tab, however
301301
* this will cause it to always reload on background -- breaking MFA.
302302
*/
303-
startActivity(intent);
303+
if (!SalesforceSDKManager.getInstance().getIsTestRun()) {
304+
startActivity(intent);
305+
}
304306
finish();
305307
}
306308
}

native/NativeSampleApps/AppConfigurator/AndroidManifest.xml

+1-3
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,14 @@
1010
android:theme="@style/AppTheme">
1111

1212
<activity android:name="com.salesforce.samples.appconfigurator.ui.MainActivity"
13-
android:label="@string/app_name"
14-
android:exported="false">
13+
android:exported="true">
1514
<intent-filter>
1615
<action android:name="android.intent.action.MAIN" />
1716
<category android:name="android.intent.category.LAUNCHER" />
1817
</intent-filter>
1918
</activity>
2019

2120
<activity android:name="com.salesforce.samples.appconfigurator.ui.EnableProfileActivity"
22-
android:label="@string/app_name"
2321
android:exported="false" />
2422

2523
<receiver android:name="com.salesforce.samples.appconfigurator.AppConfiguratorAdminReceiver"

native/NativeSampleApps/ConfiguredApp/AndroidManifest.xml

+1-2
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,8 @@
1212

1313
<!-- Launcher screen -->
1414
<activity android:name="com.salesforce.samples.configuredapp.ui.MainActivity"
15-
android:label="@string/app_name"
1615
android:theme="@style/SalesforceSDK"
17-
android:exported="false">
16+
android:exported="true">
1817

1918
<intent-filter>
2019
<action android:name="android.intent.action.MAIN" />

native/NativeSampleApps/ConfiguredApp/src/com/salesforce/samples/configuredapp/ui/MainActivity.java

+31
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,23 @@
2626
*/
2727
package com.salesforce.samples.configuredapp.ui;
2828

29+
import static android.os.Build.VERSION.SDK_INT;
30+
import static android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE;
2931
import static com.salesforce.androidsdk.R.style.SalesforceSDK;
3032
import static com.salesforce.androidsdk.R.style.SalesforceSDK_Dark;
3133

3234
import android.os.Bundle;
3335
import android.util.Log;
36+
import android.util.TypedValue;
37+
import android.view.View;
3438
import android.widget.TextView;
3539

40+
import androidx.annotation.NonNull;
41+
import androidx.core.graphics.Insets;
42+
import androidx.core.view.OnApplyWindowInsetsListener;
43+
import androidx.core.view.ViewCompat;
44+
import androidx.core.view.WindowInsetsCompat;
45+
3646
import com.salesforce.androidsdk.app.SalesforceSDKManager;
3747
import com.salesforce.androidsdk.config.BootConfig;
3848
import com.salesforce.androidsdk.rest.RestClient;
@@ -62,6 +72,27 @@ protected void onCreate(Bundle savedInstanceState) {
6272
Log.e("MainActivity.onCreate", "Could not serialize bootconfig", e);
6373
}
6474
((TextView) findViewById(R.id.bootconfig)).setText(bootconfig);
75+
76+
// Fix UI being drawn behind status and navigation bars on Android 15+
77+
if (SDK_INT > UPSIDE_DOWN_CAKE) {
78+
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.root), new OnApplyWindowInsetsListener() {
79+
@NonNull
80+
@Override
81+
public WindowInsetsCompat onApplyWindowInsets(@NonNull View v, @NonNull WindowInsetsCompat insets) {
82+
Insets mInsets = insets.getInsets(
83+
WindowInsetsCompat.Type.systemBars()
84+
& WindowInsetsCompat.Type.displayCutout()
85+
| WindowInsetsCompat.Type.displayCutout()
86+
);
87+
88+
TypedValue outValue = new TypedValue();
89+
getTheme().resolveAttribute(android.R.attr.actionBarSize, outValue, true);
90+
int actionBarHeight = TypedValue.complexToDimensionPixelSize(outValue.data, getResources().getDisplayMetrics());
91+
v.setPadding(mInsets.left, mInsets.top + actionBarHeight, mInsets.right, mInsets.bottom);
92+
return WindowInsetsCompat.CONSUMED;
93+
}
94+
});
95+
}
6596
}
6697

6798
@Override

native/NativeSampleApps/RestExplorer/src/com/salesforce/samples/restexplorer/ExplorerActivity.java

+27
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626
*/
2727
package com.salesforce.samples.restexplorer;
2828

29+
import static android.os.Build.VERSION.SDK_INT;
30+
import static android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE;
31+
2932
import android.content.ClipData;
3033
import android.content.ClipboardManager;
3134
import android.content.Context;
@@ -41,6 +44,12 @@
4144
import android.widget.TabHost;
4245
import android.widget.TextView;
4346

47+
import androidx.annotation.NonNull;
48+
import androidx.core.graphics.Insets;
49+
import androidx.core.view.OnApplyWindowInsetsListener;
50+
import androidx.core.view.ViewCompat;
51+
import androidx.core.view.WindowInsetsCompat;
52+
4453
import com.salesforce.androidsdk.accounts.UserAccount;
4554
import com.salesforce.androidsdk.accounts.UserAccountManager;
4655
import com.salesforce.androidsdk.app.SalesforceSDKManager;
@@ -130,6 +139,24 @@ protected void onCreate(Bundle savedInstanceState) {
130139
resultText.setMovementMethod(new ScrollingMovementMethod());
131140
((RestExplorerApp.RestExplorerSDKManager) RestExplorerApp.RestExplorerSDKManager.getInstance())
132141
.addDevAction(this, "Export Credentials to Clipboard", this::exportCredentials);
142+
143+
// Fix UI being drawn behind status and navigation bars on Android 15+
144+
if (SDK_INT > UPSIDE_DOWN_CAKE) {
145+
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.root), new OnApplyWindowInsetsListener() {
146+
@NonNull
147+
@Override
148+
public WindowInsetsCompat onApplyWindowInsets(@NonNull View v, @NonNull WindowInsetsCompat insets) {
149+
Insets mInsets = insets.getInsets(
150+
WindowInsetsCompat.Type.systemBars()
151+
& WindowInsetsCompat.Type.displayCutout()
152+
| WindowInsetsCompat.Type.displayCutout()
153+
);
154+
155+
v.setPadding(mInsets.left, mInsets.top, mInsets.right, mInsets.bottom);
156+
return WindowInsetsCompat.CONSUMED;
157+
}
158+
});
159+
}
133160
}
134161

135162
@Override

native/NativeSampleApps/test/RestExplorerTest/src/com/salesforce/samples/restexplorer/ServerPickerActivityTest.java

+19-27
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
*/
2727
package com.salesforce.samples.restexplorer;
2828

29-
import static androidx.test.InstrumentationRegistry.getInstrumentation;
3029
import static androidx.test.espresso.Espresso.onData;
3130
import static androidx.test.espresso.Espresso.onView;
3231
import static androidx.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu;
@@ -41,6 +40,7 @@
4140
import static androidx.test.espresso.matcher.ViewMatchers.withText;
4241
import static org.hamcrest.Matchers.allOf;
4342

43+
import android.app.Dialog;
4444
import android.app.Fragment;
4545
import android.app.FragmentManager;
4646
import android.app.FragmentTransaction;
@@ -90,20 +90,21 @@ public class ServerPickerActivityTest {
9090
private ServerPickerActivity serverPickerActivity;
9191

9292
public ActivityScenario<ServerPickerActivity> activityScenario;
93+
public static UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
9394

9495
// Dismissing system dialog if shown
9596
// See https://stackoverflow.com/questions/39457305/android-testing-waited-for-the-root-of-the-view-hierarchy-to-have-window-focus
9697
@BeforeClass
9798
public static void dismissSystemDialog() throws UiObjectNotFoundException {
98-
UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
9999
UiObject okButton = device.findObject(new UiSelector().textContains("OK"));
100100
if (okButton.exists()) {
101101
okButton.click();
102102
}
103+
SalesforceSDKManager.getInstance().setIsTestRun(true);
103104
}
104105

105106
@Before
106-
public void setUp() throws Exception {
107+
public void setUp() {
107108
eq = new EventsListenerQueue();
108109

109110
// Waits for app initialization to complete.
@@ -118,7 +119,7 @@ public void setUp() throws Exception {
118119
}
119120

120121
@After
121-
public void tearDown() throws Exception {
122+
public void tearDown() {
122123
if (eq != null) {
123124
eq.tearDown();
124125
eq = null;
@@ -129,11 +130,9 @@ public void tearDown() throws Exception {
129130

130131
/**
131132
* Test that the cancel button can be clicked and the URL not saved.
132-
*
133-
* @throws Throwable
134133
*/
135134
@Test
136-
public void testCancelButton() throws Throwable {
135+
public void testCancelButton() {
137136
openCustomEditDialog();
138137
clickView(com.salesforce.androidsdk.R.id.sf__cancel_button);
139138
Assert.assertNull("Custom URL dialog should be closed",
@@ -142,11 +141,9 @@ public void testCancelButton() throws Throwable {
142141

143142
/**
144143
* Test a valid URL can be entered and saved.
145-
*
146-
* @throws Throwable
147144
*/
148145
@Test
149-
public void testAddCustomInstance() throws Throwable {
146+
public void testAddCustomInstance() {
150147
String label = "My Custom URL";
151148
String url = "https://valid.url.com";
152149
addCustomUrl(label, url);
@@ -155,16 +152,14 @@ public void testAddCustomInstance() throws Throwable {
155152

156153
/**
157154
* Test an invalid valid URL is not entered or saved.
158-
*
159-
* @throws Throwable
160155
*/
161156
@Test
162-
public void testInvalidUrl() throws Throwable {
157+
public void testInvalidUrl() {
163158
String label = "Invalid URL";
164159
String url = "";
165160
addCustomUrl(label, url);
166-
Assert.assertTrue("Custom URL dialog should not be closed",
167-
serverPickerActivity.getCustomServerUrlEditor().getDialog().isShowing());
161+
Dialog dialog = serverPickerActivity.getCustomServerUrlEditor().getDialog();
162+
Assert.assertTrue("Custom URL dialog should not be closed", dialog != null && dialog.isShowing());
168163
try {
169164
onView(allOf(withText(label + "\n" + url), findUiElement())).check(doesNotExist());
170165
} catch (Throwable t) {
@@ -174,11 +169,9 @@ public void testInvalidUrl() throws Throwable {
174169

175170
/**
176171
* Test that https is used if http is added.
177-
*
178-
* @throws Throwable
179172
*/
180173
@Test
181-
public void testAddHttpUrl() throws Throwable {
174+
public void testAddHttpUrl() {
182175
String label = "My http URL";
183176
String httpUrl = "http://invalid.url.com";
184177
String httpsUrl = "https://invalid.url.com";
@@ -188,11 +181,9 @@ public void testAddHttpUrl() throws Throwable {
188181

189182
/**
190183
* Test that https is added is added on a url without it.
191-
*
192-
* @throws Throwable
193184
*/
194185
@Test
195-
public void testAddNoProtocolUrl() throws Throwable {
186+
public void testAddNoProtocolUrl() {
196187
String label = "No Protocol URL";
197188
String url = "basic.url.com";
198189
String httpsUrl = "https://" + url;
@@ -202,8 +193,6 @@ public void testAddNoProtocolUrl() throws Throwable {
202193

203194
/**
204195
* Test the reset button works.
205-
*
206-
* @throws Throwable
207196
*/
208197
@Test
209198
public void testResetButton() throws Throwable {
@@ -239,16 +228,17 @@ private void launchActivityBlocking() {
239228
}
240229
}
241230

242-
private void openCustomEditDialog() throws Throwable {
231+
private void openCustomEditDialog() {
232+
243233
clickView(com.salesforce.androidsdk.R.id.sf__show_custom_url_edit);
244234
final CustomServerUrlEditor dialog = serverPickerActivity.getCustomServerUrlEditor();
245-
Thread.sleep(3000);
235+
device.waitForIdle(3000);
246236
final View rootView = dialog.getRootView();
247237
Assert.assertNotNull("Root view should not be null", rootView);
248238
clickView(com.salesforce.androidsdk.R.id.sf__picker_custom_label);
249239
}
250240

251-
private void addCustomUrl(String label, String url) throws Throwable {
241+
private void addCustomUrl(String label, String url) {
252242
if (!serverPickerActivity.getCustomServerUrlEditor().isVisible()) {
253243
openCustomEditDialog();
254244
}
@@ -268,6 +258,7 @@ private void removeFragmentIfRequired() {
268258
}
269259

270260
private void setText(final int viewId, final String text) {
261+
device.waitForIdle(5000);
271262
try {
272263
onView(withId(viewId)).perform(replaceText(text), closeSoftKeyboard());
273264
} catch (Throwable t) {
@@ -276,6 +267,7 @@ private void setText(final int viewId, final String text) {
276267
}
277268

278269
private void clickView(final int resId) {
270+
device.waitForIdle(5000);
279271
try {
280272
onView(withId(resId)).perform(click());
281273
} catch (Throwable t) {
@@ -320,7 +312,7 @@ public boolean matchesSafely(View view) {
320312
}
321313

322314
private static void tapResetButton() {
323-
openActionBarOverflowOrOptionsMenu(getInstrumentation().getTargetContext());
315+
openActionBarOverflowOrOptionsMenu(InstrumentationRegistry.getInstrumentation().getTargetContext());
324316
try {
325317
onData(CoreMatchers.anything())
326318
.inRoot(RootMatchers.isPlatformPopup())

0 commit comments

Comments
 (0)