Skip to content

Commit

Permalink
Merge pull request #19139 from hrydgard/android-upgrade-sdk
Browse files Browse the repository at this point in the history
Android: Upgrade SDK and target versions, implement shortcut icons
  • Loading branch information
hrydgard authored May 13, 2024
2 parents 9ab775f + ec5eff6 commit 8fdb6e1
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 16 deletions.
17 changes: 14 additions & 3 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ androidGitVersion {
}

dependencies {
// 1.2.0 is the newest version we can use that won't complain about minSdk version.
def appcompat_version = "1.2.0"

implementation "androidx.appcompat:appcompat:$appcompat_version"
Expand All @@ -21,7 +22,7 @@ dependencies {
}

android {
flavorDimensions "variant"
flavorDimensions += "variant"
namespace 'org.ppsspp.ppsspp'
signingConfigs {
debug {
Expand All @@ -45,10 +46,20 @@ android {
}
}

compileSdk 33
compileSdk 34
ndkVersion "21.4.7075529"

defaultConfig {
/*
configurations.all {
resolutionStrategy {
// Newer versions are not compatible with our minsdk. Should find a way to exclude it entirely
// since we have no use for this transitive dependency.
force 'androidx.emoji2:emoji2-views-helper:1.0.0'
}
}
*/

applicationId 'org.ppsspp.ppsspp'
if (androidGitVersion.name() != "unknown" && androidGitVersion.code() >= 14000000) {
// Start using automatic Android version numbers from version 1.4.
Expand All @@ -63,7 +74,7 @@ android {
new File("versioncode.txt").write(androidGitVersion.code().toString())

minSdk 9
targetSdk 33
targetSdk 34
if (project.hasProperty("ANDROID_VERSION_CODE") && project.hasProperty("ANDROID_VERSION_NAME")) {
versionCode ANDROID_VERSION_CODE
versionName ANDROID_VERSION_NAME
Expand Down
59 changes: 58 additions & 1 deletion android/jni/app-android.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,8 @@ bool System_GetPropertyBool(SystemProperty prop) {
return deviceType != DEVICE_TYPE_VR;
case SYSPROP_HAS_ACCELEROMETER:
return deviceType == DEVICE_TYPE_MOBILE;
case SYSPROP_CAN_CREATE_SHORTCUT:
return false; // We can't create shortcuts directly from game code, but we can from the Android UI.
#ifndef HTTPS_NOT_AVAILABLE
case SYSPROP_SUPPORTS_HTTPS:
return !g_Config.bDisableHTTPS;
Expand Down Expand Up @@ -1662,7 +1664,7 @@ static void VulkanEmuThread(ANativeWindow *wnd) {

// NOTE: This is defunct and not working, due to how the Android storage functions currently require
// a PpssppActivity specifically and we don't have one here.
extern "C" jstring Java_org_ppsspp_ppsspp_ShortcutActivity_queryGameName(JNIEnv *env, jclass, jstring jpath) {
extern "C" jstring Java_org_ppsspp_ppsspp_ShortcutActivity_queryGameName(JNIEnv * env, jclass, jstring jpath) {
bool teardownThreadManager = false;
if (!g_threadManager.IsInitialized()) {
INFO_LOG(SYSTEM, "No thread manager - initializing one");
Expand Down Expand Up @@ -1710,3 +1712,58 @@ extern "C" jstring Java_org_ppsspp_ppsspp_ShortcutActivity_queryGameName(JNIEnv

return env->NewStringUTF(result.c_str());
}


extern "C"
JNIEXPORT jbyteArray JNICALL
Java_org_ppsspp_ppsspp_ShortcutActivity_queryGameIcon(JNIEnv * env, jclass clazz, jstring jpath) {
bool teardownThreadManager = false;
if (!g_threadManager.IsInitialized()) {
INFO_LOG(SYSTEM, "No thread manager - initializing one");
// Need a thread manager.
teardownThreadManager = true;
g_threadManager.Init(1, 1);
}
// TODO: implement requestIcon()

Path path = Path(GetJavaString(env, jpath));

INFO_LOG(SYSTEM, "queryGameIcon(%s)", path.c_str());

jbyteArray result = nullptr;

GameInfoCache *cache = new GameInfoCache();
std::shared_ptr<GameInfo> info = cache->GetInfo(nullptr, path, GameInfoFlags::ICON);
// Wait until it's done: this is synchronous, unfortunately.
if (info) {
INFO_LOG(SYSTEM, "GetInfo successful, waiting");
int attempts = 1000;
while (!info->Ready(GameInfoFlags::ICON)) {
sleep_ms(1);
attempts--;
if (!attempts) {
break;
}
}
INFO_LOG(SYSTEM, "Done waiting");
if (info->Ready(GameInfoFlags::ICON)) {
if (!info->icon.data.empty()) {
INFO_LOG(SYSTEM, "requestIcon: Got icon");
result = env->NewByteArray(info->icon.data.size());
env->SetByteArrayRegion(result, 0, info->icon.data.size(), (const jbyte *)info->icon.data.data());
}
} else {
INFO_LOG(SYSTEM, "requestIcon: Filetype unknown");
}
} else {
INFO_LOG(SYSTEM, "No info from cache");
}

delete cache;

if (teardownThreadManager) {
g_threadManager.Teardown();
}

return result;
}
44 changes: 32 additions & 12 deletions android/src/org/ppsspp/ppsspp/ShortcutActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import android.app.AlertDialog;
import android.content.Intent;
import android.content.Intent.ShortcutIconResource;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
Expand Down Expand Up @@ -75,6 +77,7 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
}

public static native String queryGameName(String path);
public static native byte[] queryGameIcon(String path);

// Create shortcut as response for ACTION_CREATE_SHORTCUT intent.
private void respondToShortcutRequest(Uri uri) {
Expand All @@ -99,13 +102,13 @@ private void respondToShortcutRequest(Uri uri) {
if (path.startsWith("content://")) {
String [] segments = path.split("/");
try {
pathStr = java.net.URLDecoder.decode(segments[segments.length - 1], StandardCharsets.UTF_8.name());
pathStr = java.net.URLDecoder.decode(segments[segments.length - 1], "UTF-8");
} catch (Exception e) {
Log.i(TAG, "Exception getting name: " + e);
}
} else if (path.startsWith("file:///")) {
try {
pathStr = java.net.URLDecoder.decode(path.substring(7), StandardCharsets.UTF_8.name());
pathStr = java.net.URLDecoder.decode(path.substring(7), "UTF-8");
} catch (Exception e) {
Log.i(TAG, "Exception getting name: " + e);
}
Expand All @@ -116,16 +119,19 @@ private void respondToShortcutRequest(Uri uri) {
String[] pathSegments = pathStr.split("/");
name = pathSegments[pathSegments.length - 1];

/*
// No longer working for various reasons.
PpssppActivity.CheckABIAndLoadLibrary();
String name = queryGameName(path);
if (name.equals("")) {
String gameName = queryGameName(path);
byte [] iconData = null;
if (gameName.equals("")) {
Log.i(TAG, "Failed to retrieve game name - ignoring.");
showBadGameMessage();
return;
}*/
// This probably happened because PPSSPP isn't running so the GameInfoCache isn't working.
// Let's just continue with our fallback name until we can fix that.
// showBadGameMessage();
// return;
} else {
name = gameName;
iconData = queryGameIcon(path);
}

Log.i(TAG, "Game name: " + name + " : Creating shortcut to " + uri.toString());

Expand All @@ -134,9 +140,23 @@ private void respondToShortcutRequest(Uri uri) {
Intent responseIntent = new Intent();
responseIntent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
responseIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME, name);
ShortcutIconResource iconResource = ShortcutIconResource.fromContext(this, R.drawable.ic_launcher);
responseIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, iconResource);

boolean setIcon = false;
if (iconData != null) {
// Try to create a PNG from the iconData.
Bitmap bmp = BitmapFactory.decodeByteArray(iconData, 0, iconData.length);
if (bmp != null) {
// Scale it to a square.
Bitmap scaledBitmap = Bitmap.createScaledBitmap(bmp, 144, 144, true);
responseIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON, scaledBitmap);
}
setIcon = true;
}
if (!setIcon) {
// Fall back to the PPSSPP icon.
ShortcutIconResource iconResource = ShortcutIconResource.fromContext(this, R.drawable.ic_launcher);
responseIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, iconResource);
}
setResult(RESULT_OK, responseIntent);

// Must call finish for result to be returned immediately
Expand Down

1 comment on commit 8fdb6e1

@appt2
Copy link

@appt2 appt2 commented on 8fdb6e1 May 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Screenshot_2024-05-13-21-21-50-957_com mi android globallauncher

Well, I downloaded and tested the program, but the game icon is not displayed, you can get help from here

Here

Please sign in to comment.