Enable libcurl on android

This commit is contained in:
Tamás Bálint Misius 2023-10-03 12:59:41 +02:00
parent f94b436cbc
commit b89d29b744
No known key found for this signature in database
GPG Key ID: 5B472A12F6ECA9F2
8 changed files with 140 additions and 6 deletions

1
.github/build.sh vendored
View File

@ -369,7 +369,6 @@ zipalign = andriod_sdk_build_tools / 'zipalign'
apksigner = andriod_sdk_build_tools / 'apksigner'
ANDROID_INI
meson_configure+=$'\t'--cross-file=.github/android-ghactions.ini
meson_configure+=$'\t'-Dhttp=false
fi
meson_configure+=$'\t'-Dc_args=[$c_args]
meson_configure+=$'\t'-Dcpp_args=[$c_args]

View File

@ -33,7 +33,7 @@
android:name="android.hardware.type.pc"
android:required="false"
/>
<uses-permission android:name="android.permission.VIBRATE" />
@ANDROID_PERMISSIONS@
<application
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
@ -43,6 +43,7 @@
>
<activity
android:name=".PowderActivity"
android:screenOrientation="landscape"
android:label="@string/app_name"
android:alwaysRetainTaskState="true"
android:launchMode="singleInstance"

View File

@ -1,7 +1,42 @@
package @APPID@;
import org.libsdl.app.SDLActivity;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.Enumeration;
import java.io.IOException;
import java.util.Base64;
public class PowderActivity extends SDLActivity
{
public static String getCertificateBundle()
{
String allPems = "";
try {
KeyStore ks = KeyStore.getInstance("AndroidCAStore");
if (ks != null) {
ks.load(null, null);
Enumeration<String> aliases = ks.aliases();
while (aliases.hasMoreElements()) {
String alias = (String)aliases.nextElement();
java.security.cert.X509Certificate cert = (java.security.cert.X509Certificate)ks.getCertificate(alias);
allPems += "-----BEGIN CERTIFICATE-----\n" + Base64.getMimeEncoder().encodeToString(cert.getEncoded()) + "\n-----END CERTIFICATE-----\n";;
}
}
} catch (IOException e) {
e.printStackTrace();
return "";
} catch (KeyStoreException e) {
e.printStackTrace();
return "";
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return "";
} catch (java.security.cert.CertificateException e) {
e.printStackTrace();
return "";
}
return allPems;
}
}

View File

@ -173,9 +173,6 @@ elif lua_variant == 'luajit'
endif
enable_http = get_option('http')
if host_platform == 'android'
enable_http = false
endif
if host_platform == 'android'
android_ndk_toolchain_prefix = meson.get_external_property('android_ndk_toolchain_prefix')
android_platform = meson.get_external_property('android_platform')

View File

@ -0,0 +1,86 @@
#include "CurlError.h"
#include "common/String.h"
#include "Config.h"
#include <iostream>
#include <SDL.h>
#include <jni.h>
#include <android/log.h>
static jclass FindClass(JNIEnv *env, const char *name)
{
jobject nativeActivity = (jobject)SDL_AndroidGetActivity(); if (!nativeActivity) return NULL;
jclass acl = env->GetObjectClass(nativeActivity); if (!acl ) return NULL;
jmethodID getClassLoader = env->GetMethodID(acl, "getClassLoader", "()Ljava/lang/ClassLoader;"); if (!getClassLoader) return NULL;
jobject cls = env->CallObjectMethod(nativeActivity, getClassLoader); if (!cls ) return NULL;
jclass classLoader = env->FindClass("java/lang/ClassLoader"); if (!classLoader ) return NULL;
jmethodID findClass = env->GetMethodID(classLoader, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;"); if (!findClass ) return NULL;
jstring strClassName = env->NewStringUTF(name); if (!strClassName ) return NULL;
jclass clazz = (jclass)(env->CallObjectMethod(cls, findClass, strClassName));
env->DeleteLocalRef(strClassName);
return clazz;
}
namespace http
{
void UseSystemCertProvider(CURL *easy)
{
struct DoOnce
{
ByteString allPems;
void InitPem()
{
auto die = [](ByteString message) {
__android_log_print(ANDROID_LOG_ERROR, "AndroidCertProvider", "%s", ("failed to enumerate system certificates: " + message).c_str());
};
auto *env = (JNIEnv *)SDL_AndroidGetJNIEnv();
if (!env)
{
return die("SDL_AndroidGetJNIEnv failed");
}
jclass mPowderActivity = FindClass(env, ByteString::Build(APPID, ".PowderActivity").c_str());
if (!mPowderActivity)
{
return die("FindClass failed");
}
jmethodID midGetCertificateBundle = env->GetStaticMethodID(mPowderActivity, "getCertificateBundle", "()Ljava/lang/String;");
if (!midGetCertificateBundle)
{
return die("GetStaticMethodID failed");
}
jstring str = (jstring)env->CallStaticObjectMethod(mPowderActivity, midGetCertificateBundle);
if (!str)
{
return die("getCertificateBundle failed");
}
const char *utf = env->GetStringUTFChars(str, 0);
if (utf)
{
allPems = utf;
env->ReleaseStringUTFChars(str, utf);
}
else
{
__android_log_print(ANDROID_LOG_ERROR, "AndroidCertProvider", "out of memory???");
}
env->DeleteLocalRef(str);
__android_log_print(ANDROID_LOG_ERROR, "AndroidCertProvider", "certificate bundle loaded");
}
DoOnce()
{
InitPem();
}
};
static DoOnce doOnce;
if (doOnce.allPems.size())
{
curl_blob blob;
blob.data = &doOnce.allPems[0];
blob.len = doOnce.allPems.size();
blob.flags = CURL_BLOB_COPY;
HandleCURLcode(curl_easy_setopt(easy, CURLOPT_CAINFO_BLOB, &blob));
}
}
}

View File

@ -13,6 +13,10 @@ else
use_system_cert_provider = true
client_files += files('WindowsCertProvider.cpp')
endif
if host_platform == 'android'
use_system_cert_provider = true
client_files += files('AndroidCertProvider.cpp')
endif
endif
conf_data.set('NOHTTP', (not enable_http).to_string())
conf_data.set('USE_SYSTEM_CERT_PROVIDER', use_system_cert_provider.to_string())

View File

@ -10,7 +10,7 @@
class Simulation;
class Brush;
class VideoBuffer;
class Particle;
struct Particle;
class Tool
{

View File

@ -49,6 +49,18 @@ conf_data.set('APPID', app_id)
conf_data.set('APPDATA', get_option('app_data'))
conf_data.set('APPVENDOR', get_option('app_vendor'))
if host_platform == 'android'
android_permissions = [
'<uses-permission android:name="android.permission.VIBRATE" />',
]
if enable_http
android_permissions += [
'<uses-permission android:name="android.permission.INTERNET" />',
]
endif
conf_data.set('ANDROID_PERMISSIONS', '\n'.join(android_permissions))
endif
powder_files = files(
'SDLCompat.cpp',
'PowderToySDL.cpp',