[android] Provide a path instead of throwing NPE when getDir() suites returns null (flutter/engine#30367)
This commit is contained in:
@@ -6,21 +6,52 @@ package io.flutter.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import java.io.File;
|
||||
|
||||
public final class PathUtils {
|
||||
public static String getFilesDir(Context applicationContext) {
|
||||
return applicationContext.getFilesDir().getPath();
|
||||
File filesDir = applicationContext.getFilesDir();
|
||||
if (filesDir == null) {
|
||||
filesDir = new File(getDataDirPath(applicationContext), "files");
|
||||
}
|
||||
return filesDir.getPath();
|
||||
}
|
||||
|
||||
public static String getDataDirectory(Context applicationContext) {
|
||||
return applicationContext.getDir("flutter", Context.MODE_PRIVATE).getPath();
|
||||
final String name = "flutter";
|
||||
File flutterDir = applicationContext.getDir(name, Context.MODE_PRIVATE);
|
||||
if (flutterDir == null) {
|
||||
flutterDir = new File(getDataDirPath(applicationContext), "app_" + name);
|
||||
}
|
||||
return flutterDir.getPath();
|
||||
}
|
||||
|
||||
public static String getCacheDirectory(Context applicationContext) {
|
||||
File cacheDir;
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
return applicationContext.getCodeCacheDir().getPath();
|
||||
cacheDir = applicationContext.getCodeCacheDir();
|
||||
if (cacheDir == null) {
|
||||
cacheDir = applicationContext.getCacheDir();
|
||||
}
|
||||
} else {
|
||||
return applicationContext.getCacheDir().getPath();
|
||||
cacheDir = applicationContext.getCacheDir();
|
||||
}
|
||||
if (cacheDir == null) {
|
||||
// This can happen if the disk is full. This code path is used to set up dart:io's
|
||||
// `Directory.systemTemp`. It's unknown if the application will ever try to
|
||||
// use that or not, so do not throw here. In this case, this directory does
|
||||
// not exist because the disk is full, and the application will later get an
|
||||
// exception when it tries to actually write.
|
||||
cacheDir = new File(getDataDirPath(applicationContext), "cache");
|
||||
}
|
||||
return cacheDir.getPath();
|
||||
}
|
||||
|
||||
private static String getDataDirPath(Context applicationContext) {
|
||||
if (Build.VERSION.SDK_INT >= 24) {
|
||||
return applicationContext.getDataDir().getPath();
|
||||
} else {
|
||||
return applicationContext.getApplicationInfo().dataDir;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
package io.flutter.util;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import java.io.File;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
@Config(manifest = Config.NONE)
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class PathUtilsTest {
|
||||
|
||||
private static final String APP_DATA_PATH = "/data/data/package_name";
|
||||
|
||||
@Test
|
||||
public void canGetFilesDir() {
|
||||
Context context = mock(Context.class);
|
||||
when(context.getFilesDir()).thenReturn(new File(APP_DATA_PATH + "/files"));
|
||||
assertEquals(PathUtils.getFilesDir(context), APP_DATA_PATH + "/files");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canOnlyGetFilesPathWhenDiskFullAndFilesDirNotCreated() {
|
||||
Context context = mock(Context.class);
|
||||
when(context.getFilesDir()).thenReturn(null);
|
||||
if (Build.VERSION.SDK_INT >= 24) {
|
||||
when(context.getDataDir()).thenReturn(new File(APP_DATA_PATH));
|
||||
} else {
|
||||
when(context.getApplicationInfo().dataDir).thenReturn(APP_DATA_PATH);
|
||||
}
|
||||
assertEquals(PathUtils.getFilesDir(context), APP_DATA_PATH + "/files");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canGetFlutterDataDir() {
|
||||
Context context = mock(Context.class);
|
||||
when(context.getDir("flutter", Context.MODE_PRIVATE))
|
||||
.thenReturn(new File(APP_DATA_PATH + "/app_flutter"));
|
||||
assertEquals(PathUtils.getDataDirectory(context), APP_DATA_PATH + "/app_flutter");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canOnlyGetFlutterDataPathWhenDiskFullAndFlutterDataDirNotCreated() {
|
||||
Context context = mock(Context.class);
|
||||
when(context.getDir("flutter", Context.MODE_PRIVATE)).thenReturn(null);
|
||||
if (Build.VERSION.SDK_INT >= 24) {
|
||||
when(context.getDataDir()).thenReturn(new File(APP_DATA_PATH));
|
||||
} else {
|
||||
when(context.getApplicationInfo().dataDir).thenReturn(APP_DATA_PATH);
|
||||
}
|
||||
assertEquals(PathUtils.getDataDirectory(context), APP_DATA_PATH + "/app_flutter");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canGetCacheDir() {
|
||||
Context context = mock(Context.class);
|
||||
when(context.getCacheDir()).thenReturn(new File(APP_DATA_PATH + "/cache"));
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
when(context.getCodeCacheDir()).thenReturn(new File(APP_DATA_PATH + "/code_cache"));
|
||||
}
|
||||
assertTrue(PathUtils.getCacheDirectory(context).startsWith(APP_DATA_PATH));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canOnlyGetCachePathWhenDiskFullAndCacheDirNotCreated() {
|
||||
Context context = mock(Context.class);
|
||||
when(context.getCacheDir()).thenReturn(null);
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
when(context.getCodeCacheDir()).thenReturn(null);
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= 24) {
|
||||
when(context.getDataDir()).thenReturn(new File(APP_DATA_PATH));
|
||||
} else {
|
||||
when(context.getApplicationInfo().dataDir).thenReturn(APP_DATA_PATH);
|
||||
}
|
||||
assertEquals(PathUtils.getCacheDirectory(context), APP_DATA_PATH + "/cache");
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@
|
||||
<manifest file="../../../flutter/shell/platform/android/AndroidManifest.xml" />
|
||||
<src file="../../../flutter/shell/platform/android/test/io/flutter/TestUtils.java" />
|
||||
<src file="../../../flutter/shell/platform/android/test/io/flutter/SmokeTest.java" />
|
||||
<src file="../../../flutter/shell/platform/android/test/io/flutter/util/PathUtilsTest.java" />
|
||||
<src file="../../../flutter/shell/platform/android/test/io/flutter/util/ViewUtilsTest.java" />
|
||||
<src file="../../../flutter/shell/platform/android/test/io/flutter/util/PreconditionsTest.java" />
|
||||
<src file="../../../flutter/shell/platform/android/test/io/flutter/util/FakeKeyEvent.java" />
|
||||
@@ -72,6 +73,7 @@
|
||||
<src file="../../../flutter/shell/platform/android/io/flutter/util/PathUtils.java" />
|
||||
<src file="../../../flutter/shell/platform/android/io/flutter/embedding/android/KeyboardManager.java" />
|
||||
<src file="../../../flutter/shell/platform/android/io/flutter/embedding/android/AndroidTouchProcessor.java" />
|
||||
<src file="../../../flutter/shell/platform/android/io/flutter/embedding/android/FlutterPlayStoreSplitApplication.java" />
|
||||
<src file="../../../flutter/shell/platform/android/io/flutter/embedding/android/RenderMode.java" />
|
||||
<src file="../../../flutter/shell/platform/android/io/flutter/embedding/android/FlutterFragmentActivity.java" />
|
||||
<src file="../../../flutter/shell/platform/android/io/flutter/embedding/android/FlutterActivity.java" />
|
||||
@@ -83,6 +85,7 @@
|
||||
<src file="../../../flutter/shell/platform/android/io/flutter/embedding/android/FlutterTextureView.java" />
|
||||
<src file="../../../flutter/shell/platform/android/io/flutter/embedding/android/MotionEventTracker.java" />
|
||||
<src file="../../../flutter/shell/platform/android/io/flutter/embedding/android/SplashScreenProvider.java" />
|
||||
<src file="../../../flutter/shell/platform/android/io/flutter/embedding/android/WindowInfoRepositoryCallbackAdapterWrapper.java" />
|
||||
<src file="../../../flutter/shell/platform/android/io/flutter/embedding/android/TransparencyMode.java" />
|
||||
<src file="../../../flutter/shell/platform/android/io/flutter/embedding/android/FlutterEngineProvider.java" />
|
||||
<src file="../../../flutter/shell/platform/android/io/flutter/embedding/android/FlutterFragment.java" />
|
||||
@@ -116,6 +119,7 @@
|
||||
<src file="../../../flutter/shell/platform/android/io/flutter/embedding/engine/plugins/broadcastreceiver/BroadcastReceiverAware.java" />
|
||||
<src file="../../../flutter/shell/platform/android/io/flutter/embedding/engine/plugins/broadcastreceiver/BroadcastReceiverControlSurface.java" />
|
||||
<src file="../../../flutter/shell/platform/android/io/flutter/embedding/engine/plugins/broadcastreceiver/BroadcastReceiverPluginBinding.java" />
|
||||
<src file="../../../flutter/shell/platform/android/io/flutter/embedding/engine/dart/PlatformTaskQueue.java" />
|
||||
<src file="../../../flutter/shell/platform/android/io/flutter/embedding/engine/dart/DartExecutor.java" />
|
||||
<src file="../../../flutter/shell/platform/android/io/flutter/embedding/engine/dart/PlatformMessageHandler.java" />
|
||||
<src file="../../../flutter/shell/platform/android/io/flutter/embedding/engine/dart/DartMessenger.java" />
|
||||
|
||||
Reference in New Issue
Block a user