Update to Android SDK 25

This handles the new permission system in Android M.
This commit is contained in:
Mahdi Hijazi 2017-03-24 21:21:29 +01:00
parent c5cc781205
commit 8f2f833f9d
6 changed files with 156 additions and 20 deletions

View File

@ -18,7 +18,7 @@ android {
// TODO If this is ever modified, change application_id in strings.xml
applicationId "org.dolphinemu.dolphinemu"
minSdkVersion 21
targetSdkVersion 21
targetSdkVersion 25
// TODO This should be set to the Buildbot build number for release builds, and be "1" for debug builds.
versionCode 13
@ -72,13 +72,13 @@ android {
}
dependencies {
compile 'com.android.support:support-v13:25.2.0'
compile 'com.android.support:cardview-v7:25.2.0'
compile 'com.android.support:recyclerview-v7:25.2.0'
compile 'com.android.support:design:25.2.0'
compile 'com.android.support:support-v13:25.3.0'
compile 'com.android.support:cardview-v7:25.3.0'
compile 'com.android.support:recyclerview-v7:25.3.0'
compile 'com.android.support:design:25.3.0'
// Android TV UI libraries.
compile 'com.android.support:leanback-v17:25.2.0'
compile 'com.android.support:leanback-v17:25.3.0'
// For showing the banner as a circle a-la Material Design Guidelines
compile 'de.hdodenhof:circleimageview:2.1.0'

View File

@ -1,6 +1,7 @@
package org.dolphinemu.dolphinemu.ui.main;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.os.Bundle;
import android.support.annotation.Nullable;
@ -13,6 +14,7 @@ import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;
import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.activities.AddDirectoryActivity;
@ -20,6 +22,7 @@ import org.dolphinemu.dolphinemu.adapters.PlatformPagerAdapter;
import org.dolphinemu.dolphinemu.model.GameProvider;
import org.dolphinemu.dolphinemu.ui.platform.PlatformGamesView;
import org.dolphinemu.dolphinemu.ui.settings.SettingsActivity;
import org.dolphinemu.dolphinemu.utils.PermissionsHandler;
import org.dolphinemu.dolphinemu.utils.StartupHandler;
/**
@ -45,9 +48,6 @@ public final class MainActivity extends AppCompatActivity implements MainView
setSupportActionBar(mToolbar);
PlatformPagerAdapter platformPagerAdapter = new PlatformPagerAdapter(getFragmentManager(), this);
mViewPager.setAdapter(platformPagerAdapter);
mTabLayout.setupWithViewPager(mViewPager);
// Set up the FAB.
@ -66,6 +66,14 @@ public final class MainActivity extends AppCompatActivity implements MainView
// TODO Split some of this stuff into Application.onCreate()
if (savedInstanceState == null)
StartupHandler.HandleInit(this);
if (PermissionsHandler.hasWriteAccess(this))
{
PlatformPagerAdapter platformPagerAdapter = new PlatformPagerAdapter(getFragmentManager(), this);
mViewPager.setAdapter(platformPagerAdapter);
} else {
mViewPager.setVisibility(View.INVISIBLE);
}
}
// TODO: Replace with a ButterKnife injection.
@ -145,6 +153,28 @@ public final class MainActivity extends AppCompatActivity implements MainView
mPresenter.handleActivityResult(requestCode, resultCode);
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case PermissionsHandler.REQUEST_CODE_WRITE_PERMISSION:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
StartupHandler.copyAssetsIfNeeded(this);
PlatformPagerAdapter platformPagerAdapter = new PlatformPagerAdapter(getFragmentManager(), this);
mViewPager.setAdapter(platformPagerAdapter);
mTabLayout.setupWithViewPager(mViewPager);
mViewPager.setVisibility(View.VISIBLE);
} else {
Toast.makeText(this, R.string.write_permission_needed, Toast.LENGTH_SHORT)
.show();
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
break;
}
}
/**
* Called by the framework whenever any actionbar/toolbar icon is clicked.
*

View File

@ -3,6 +3,7 @@ package org.dolphinemu.dolphinemu.ui.main;
import android.app.Activity;
import android.app.FragmentManager;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.os.Bundle;
import android.support.v17.leanback.app.BrowseFragment;
@ -16,6 +17,7 @@ import android.support.v17.leanback.widget.OnItemViewClickedListener;
import android.support.v17.leanback.widget.Presenter;
import android.support.v17.leanback.widget.Row;
import android.support.v17.leanback.widget.RowPresenter;
import android.widget.Toast;
import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.activities.AddDirectoryActivity;
@ -25,6 +27,7 @@ import org.dolphinemu.dolphinemu.adapters.SettingsRowPresenter;
import org.dolphinemu.dolphinemu.model.Game;
import org.dolphinemu.dolphinemu.model.TvSettingsItem;
import org.dolphinemu.dolphinemu.ui.settings.SettingsActivity;
import org.dolphinemu.dolphinemu.utils.PermissionsHandler;
import org.dolphinemu.dolphinemu.utils.StartupHandler;
import org.dolphinemu.dolphinemu.viewholders.TvGameViewHolder;
@ -148,14 +151,31 @@ public final class TvMainActivity extends Activity implements MainView
mPresenter.handleActivityResult(requestCode, resultCode);
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case PermissionsHandler.REQUEST_CODE_WRITE_PERMISSION:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
StartupHandler.copyAssetsIfNeeded(this);
loadGames();
} else {
Toast.makeText(this, R.string.write_permission_needed, Toast.LENGTH_SHORT)
.show();
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
break;
}
}
private void buildRowsAdapter()
{
mRowsAdapter = new ArrayObjectAdapter(new ListRowPresenter());
// For each platform
for (int platformIndex = 0; platformIndex <= Game.PLATFORM_ALL; ++platformIndex)
if (PermissionsHandler.hasWriteAccess(this))
{
mPresenter.loadGames(platformIndex);
loadGames();
}
mRowsAdapter.add(buildSettingsRow());
@ -163,6 +183,13 @@ public final class TvMainActivity extends Activity implements MainView
mBrowseFragment.setAdapter(mRowsAdapter);
}
private void loadGames() {
// For each platform
for (int platformIndex = 0; platformIndex <= Game.PLATFORM_ALL; ++platformIndex) {
mPresenter.loadGames(platformIndex);
}
}
private ListRow buildGamesRow(int platform, Cursor games)
{
// Create an adapter for this row.

View File

@ -0,0 +1,71 @@
package org.dolphinemu.dolphinemu.utils;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.os.Build;
import android.support.v4.content.ContextCompat;
import android.widget.Toast;
import org.dolphinemu.dolphinemu.R;
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
public class PermissionsHandler {
public static final int REQUEST_CODE_WRITE_PERMISSION = 500;
@TargetApi(Build.VERSION_CODES.M)
public static boolean checkWritePermission(final Activity activity) {
if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
return true;
}
int hasWritePermission = ContextCompat.checkSelfPermission(activity, WRITE_EXTERNAL_STORAGE);
if (hasWritePermission != PackageManager.PERMISSION_GRANTED) {
if (activity.shouldShowRequestPermissionRationale(WRITE_EXTERNAL_STORAGE)) {
showMessageOKCancel(activity, activity.getString(R.string.write_permission_needed),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
activity.requestPermissions(new String[] {WRITE_EXTERNAL_STORAGE},
REQUEST_CODE_WRITE_PERMISSION);
}
});
return false;
}
activity.requestPermissions(new String[] {WRITE_EXTERNAL_STORAGE},
REQUEST_CODE_WRITE_PERMISSION);
return false;
}
return true;
}
public static boolean hasWriteAccess(Activity activity) {
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
int hasWritePermission = ContextCompat.checkSelfPermission(activity, WRITE_EXTERNAL_STORAGE);
return hasWritePermission == PackageManager.PERMISSION_GRANTED;
}
return true;
}
private static void showMessageOKCancel(final Activity activity, String message, DialogInterface.OnClickListener okListener) {
new AlertDialog.Builder(activity)
.setMessage(message)
.setPositiveButton(android.R.string.ok, okListener)
.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Toast.makeText(activity, R.string.write_permission_needed, Toast.LENGTH_SHORT)
.show();
}
})
.create()
.show();
}
}

View File

@ -17,15 +17,9 @@ public final class StartupHandler
{
NativeLibrary.SetUserDirectory(""); // Auto-Detect
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(parent);
boolean assetsCopied = preferences.getBoolean("assetsCopied", false);
// Only perform these extensive copy operations once.
if (!assetsCopied)
{
// Copy assets into appropriate locations.
Intent copyAssets = new Intent(parent, AssetCopyService.class);
parent.startService(copyAssets);
if (PermissionsHandler.checkWritePermission(parent)) {
copyAssetsIfNeeded(parent);
}
Intent intent = parent.getIntent();
@ -51,4 +45,16 @@ public final class StartupHandler
}
return false;
}
public static void copyAssetsIfNeeded(Activity parent) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(parent);
boolean assetsCopied = preferences.getBoolean("assetsCopied", false);
if (!assetsCopied)
{
// Copy assets into appropriate locations.
Intent copyAssets = new Intent(parent, AssetCopyService.class);
parent.startService(copyAssets);
}
}
}

View File

@ -238,4 +238,6 @@
<!-- Package Names-->
<string name="application_id">org.dolphinemu.dolphinemu</string>
<string name="write_permission_needed">You need to allow write access to external storage for the emulator to work</string>
</resources>