You've already forked android_translation_layer
mirror of
https://gitlab.com/android_translation_layer/android_translation_layer.git
synced 2025-10-27 11:48:10 -07:00
src/main-executable: show actual package name as window title, preparation for showing app icon, re-add some missing stuff
This commit is contained in:
@@ -1,10 +1,23 @@
|
|||||||
package android.app;
|
package android.app;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
|
import com.reandroid.apk.AndroidFrameworks;
|
||||||
|
import com.reandroid.arsc.chunk.xml.AndroidManifestBlock;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
public class Application extends Context {
|
public class Application extends Context {
|
||||||
|
private String app_icon_path = null;
|
||||||
|
|
||||||
|
private String get_app_icon_path() {
|
||||||
|
return app_icon_path;
|
||||||
|
}
|
||||||
|
|
||||||
public interface ActivityLifecycleCallbacks {
|
public interface ActivityLifecycleCallbacks {
|
||||||
void onActivityCreated(Activity activity, Bundle savedInstanceState);
|
void onActivityCreated(Activity activity, Bundle savedInstanceState);
|
||||||
void onActivityStarted(Activity activity);
|
void onActivityStarted(Activity activity);
|
||||||
@@ -28,7 +41,17 @@ public class Application extends Context {
|
|||||||
*/
|
*/
|
||||||
public void onProvideAssistData(Activity activity, Bundle data);
|
public void onProvideAssistData(Activity activity, Bundle data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Application() {
|
public Application() {
|
||||||
|
/* TODO: is this the right place to put this? */
|
||||||
|
InputStream inStream = ClassLoader.getSystemClassLoader().getResourceAsStream("AndroidManifest.xml");
|
||||||
|
try {
|
||||||
|
AndroidManifestBlock manifest = AndroidManifestBlock.load(inStream);
|
||||||
|
int app_icon_resid = manifest.getIconResourceId();
|
||||||
|
app_icon_path = this.getResources().getString(app_icon_resid);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Called when the application is starting, before any activity, service,
|
* Called when the application is starting, before any activity, service,
|
||||||
|
|||||||
@@ -33,10 +33,13 @@ import android.util.DisplayMetrics;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
import android.view.WindowManagerImpl;
|
import android.view.WindowManagerImpl;
|
||||||
|
import com.reandroid.arsc.chunk.xml.AndroidManifestBlock;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
public class Context extends Object {
|
public class Context extends Object {
|
||||||
private final static String TAG = "Context";
|
private final static String TAG = "Context";
|
||||||
@@ -46,6 +49,8 @@ public class Context extends Object {
|
|||||||
public static final String AUDIO_SERVICE = "audio";
|
public static final String AUDIO_SERVICE = "audio";
|
||||||
public static final String DISPLAY_SERVICE = "display";
|
public static final String DISPLAY_SERVICE = "display";
|
||||||
public static final String MEDIA_ROUTER_SERVICE = "media_router";
|
public static final String MEDIA_ROUTER_SERVICE = "media_router";
|
||||||
|
public static final String WINDOW_SERVICE = "window";
|
||||||
|
private static AndroidManifestBlock manifest = null;
|
||||||
|
|
||||||
static AssetManager assets;
|
static AssetManager assets;
|
||||||
static DisplayMetrics dm;
|
static DisplayMetrics dm;
|
||||||
@@ -70,6 +75,13 @@ public class Context extends Object {
|
|||||||
r = new Resources(assets, dm, config);
|
r = new Resources(assets, dm, config);
|
||||||
this_application = new Application(); // TODO: the application context is presumably not identical to the Activity context, what is the difference for us though?
|
this_application = new Application(); // TODO: the application context is presumably not identical to the Activity context, what is the difference for us though?
|
||||||
application_info = new ApplicationInfo();
|
application_info = new ApplicationInfo();
|
||||||
|
|
||||||
|
InputStream inStream = ClassLoader.getSystemClassLoader().getResourceAsStream("AndroidManifest.xml");
|
||||||
|
try {
|
||||||
|
manifest = AndroidManifestBlock.load(inStream);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Context() {
|
public Context() {
|
||||||
@@ -156,7 +168,7 @@ public class Context extends Object {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getPackageName() {
|
public String getPackageName() {
|
||||||
return "com.example.demo_app";
|
return manifest.getPackageName();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPackageCodePath() {
|
public String getPackageCodePath() {
|
||||||
@@ -254,7 +266,7 @@ public class Context extends Object {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public SharedPreferences getSharedPreferences(String name, int mode) {
|
public SharedPreferences getSharedPreferences(String name, int mode) {
|
||||||
System.out.println("\n\n...> getSharedPreferences(" + name + ",)\n\n");
|
System.out.println("\n\n...> getSharedPreferences(" + name + ")\n\n");
|
||||||
File prefsFile = getSharedPrefsFile(name);
|
File prefsFile = getSharedPrefsFile(name);
|
||||||
return new SharedPreferencesImpl(prefsFile, mode);
|
return new SharedPreferencesImpl(prefsFile, mode);
|
||||||
}
|
}
|
||||||
@@ -289,6 +301,18 @@ public class Context extends Object {
|
|||||||
|
|
||||||
public void registerComponentCallbacks(ComponentCallbacks callbacks) {}
|
public void registerComponentCallbacks(ComponentCallbacks callbacks) {}
|
||||||
|
|
||||||
|
public boolean bindService(Intent dummy, ServiceConnection dummy2, int dummy3) {
|
||||||
|
System.out.println("bindService("+dummy+", "+dummy2+", "+dummy3+")");
|
||||||
|
return false; // maybe?
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startActivity(Intent intent) {
|
||||||
|
System.out.println("------------------");
|
||||||
|
System.out.println("app wants to startActivity("+intent+"), but we don't support that... :/");
|
||||||
|
try { throw new java.lang.Exception(); } catch (java.lang.Exception e) { e.printStackTrace(); }
|
||||||
|
System.out.println("------------------");
|
||||||
|
}
|
||||||
|
|
||||||
// these may not look like typical stubs, but they definitely are stubs
|
// these may not look like typical stubs, but they definitely are stubs
|
||||||
public final TypedArray obtainStyledAttributes(AttributeSet set, int[] attrs) { return new TypedArray(r, new int[1000], new int[1000], 0); }
|
public final TypedArray obtainStyledAttributes(AttributeSet set, int[] attrs) { return new TypedArray(r, new int[1000], new int[1000], 0); }
|
||||||
public final TypedArray obtainStyledAttributes(AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes) { return new TypedArray(r, new int[1000], new int[1000], 0); }
|
public final TypedArray obtainStyledAttributes(AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes) { return new TypedArray(r, new int[1000], new int[1000], 0); }
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <libgen.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
@@ -155,6 +156,7 @@ static void open(GtkApplication *app, GFile** files, gint nfiles, const gchar* h
|
|||||||
char *api_impl_jar;
|
char *api_impl_jar;
|
||||||
char *microg_apk = NULL;
|
char *microg_apk = NULL;
|
||||||
char *framework_res_apk = NULL;
|
char *framework_res_apk = NULL;
|
||||||
|
const char *package_name;
|
||||||
int errno_libdir;
|
int errno_libdir;
|
||||||
int errno_localdir;
|
int errno_localdir;
|
||||||
int ret;
|
int ret;
|
||||||
@@ -306,6 +308,23 @@ static void open(GtkApplication *app, GFile** files, gint nfiles, const gchar* h
|
|||||||
|
|
||||||
set_up_handle_cache(env);
|
set_up_handle_cache(env);
|
||||||
|
|
||||||
|
/* -- register our JNI library under the appropriate classloader -- */
|
||||||
|
|
||||||
|
/* 'android/view/View' is part of the "hax.dex" package, any other function from that package would serve just as well */
|
||||||
|
jmethodID getClassLoader = _METHOD((*env)->FindClass(env, "java/lang/Class"), "getClassLoader", "()Ljava/lang/ClassLoader;");
|
||||||
|
jobject class_loader = (*env)->CallObjectMethod(env, (*env)->FindClass(env, "android/view/View"), getClassLoader);
|
||||||
|
|
||||||
|
jclass java_runtime_class = (*env)->FindClass(env, "java/lang/Runtime");
|
||||||
|
|
||||||
|
jmethodID getRuntime = _STATIC_METHOD(java_runtime_class, "getRuntime", "()Ljava/lang/Runtime;");
|
||||||
|
jobject java_runtime = (*env)->CallStaticObjectMethod(env, java_runtime_class, getRuntime);
|
||||||
|
|
||||||
|
/* this method is private, but it seems we get away with calling it from C */
|
||||||
|
jmethodID loadLibrary_with_classloader = _METHOD(java_runtime_class, "loadLibrary", "(Ljava/lang/String;Ljava/lang/ClassLoader;)V");
|
||||||
|
(*env)->CallVoidMethod(env, java_runtime, loadLibrary_with_classloader, _JSTRING("translation_layer_main"), class_loader);
|
||||||
|
|
||||||
|
/* -- misc -- */
|
||||||
|
|
||||||
jclass display_class = (*env)->FindClass(env, "android/view/Display");
|
jclass display_class = (*env)->FindClass(env, "android/view/Display");
|
||||||
_SET_STATIC_INT_FIELD(display_class, "window_width", d->window_width);
|
_SET_STATIC_INT_FIELD(display_class, "window_width", d->window_width);
|
||||||
_SET_STATIC_INT_FIELD(display_class, "window_height", d->window_height);
|
_SET_STATIC_INT_FIELD(display_class, "window_height", d->window_height);
|
||||||
@@ -319,32 +338,10 @@ static void open(GtkApplication *app, GFile** files, gint nfiles, const gchar* h
|
|||||||
|
|
||||||
window = gtk_application_window_new(app);
|
window = gtk_application_window_new(app);
|
||||||
|
|
||||||
gtk_window_set_title(GTK_WINDOW(window), "com.example.demo_application");
|
|
||||||
gtk_window_set_default_size(GTK_WINDOW(window), d->window_width, d->window_height);
|
|
||||||
g_signal_connect(window, "close-request", G_CALLBACK (app_exit), env);
|
|
||||||
|
|
||||||
// TODO: set icon according to how android gets it for the purposes of displaying it in the launcher
|
|
||||||
// gtk_window_set_icon_name(window, "weather-clear");
|
|
||||||
|
|
||||||
if(getenv("ATL_DISABLE_WINDOW_DECORATIONS"))
|
if(getenv("ATL_DISABLE_WINDOW_DECORATIONS"))
|
||||||
gtk_window_set_decorated(GTK_WINDOW(window), 0);
|
gtk_window_set_decorated(GTK_WINDOW(window), 0);
|
||||||
|
|
||||||
gtk_widget_show(window);
|
gtk_window_present(GTK_WINDOW(window));
|
||||||
|
|
||||||
/* -- register our JNI library under the appropriate classloader -- */
|
|
||||||
|
|
||||||
/* 'android/view/View' is part of the "hax.dex" package, any other function from that package would serve just as well */
|
|
||||||
jmethodID getClassLoader = _METHOD((*env)->FindClass(env, "java/lang/Class"), "getClassLoader", "()Ljava/lang/ClassLoader;");
|
|
||||||
jobject class_loader = (*env)->CallObjectMethod(env, handle_cache.view.class, getClassLoader);
|
|
||||||
|
|
||||||
jclass java_runtime_class = (*env)->FindClass(env, "java/lang/Runtime");
|
|
||||||
|
|
||||||
jmethodID getRuntime = _STATIC_METHOD(java_runtime_class, "getRuntime", "()Ljava/lang/Runtime;");
|
|
||||||
jobject java_runtime = (*env)->CallStaticObjectMethod(env, java_runtime_class, getRuntime);
|
|
||||||
|
|
||||||
/* this method is private, but it seems we get away with calling it from C */
|
|
||||||
jmethodID loadLibrary_with_classloader = _METHOD(java_runtime_class, "loadLibrary", "(Ljava/lang/String;Ljava/lang/ClassLoader;)V");
|
|
||||||
(*env)->CallVoidMethod(env, java_runtime, loadLibrary_with_classloader, _JSTRING("translation_layer_main"), class_loader);
|
|
||||||
|
|
||||||
extract_from_apk("assets/", "assets/");
|
extract_from_apk("assets/", "assets/");
|
||||||
/* extract native libraries from apk*/
|
/* extract native libraries from apk*/
|
||||||
@@ -359,6 +356,45 @@ static void open(GtkApplication *app, GFile** files, gint nfiles, const gchar* h
|
|||||||
if((*env)->ExceptionCheck(env))
|
if((*env)->ExceptionCheck(env))
|
||||||
(*env)->ExceptionDescribe(env);
|
(*env)->ExceptionDescribe(env);
|
||||||
|
|
||||||
|
|
||||||
|
/* -- set the window title and (FIXME) app icon -- */
|
||||||
|
|
||||||
|
package_name = _CSTRING((*env)->CallObjectMethod(env, activity_object, handle_cache.context.get_package_name));
|
||||||
|
if((*env)->ExceptionCheck(env))
|
||||||
|
(*env)->ExceptionDescribe(env);
|
||||||
|
|
||||||
|
/* const char *app_icon_path = _CSTRING((*env)->CallObjectMethod(env, handle_cache.application.object, handle_cache.application.get_app_icon_path));
|
||||||
|
if((*env)->ExceptionCheck(env))
|
||||||
|
(*env)->ExceptionDescribe(env);
|
||||||
|
|
||||||
|
char *tmp = strdup(app_icon_path);
|
||||||
|
const char *app_icon_dirname = dirname(tmp);
|
||||||
|
char *app_icon_basename = basename(app_icon_path);
|
||||||
|
*strrchr(app_icon_basename, '.') = '\0';
|
||||||
|
extract_from_apk(app_icon_path, app_icon_path);
|
||||||
|
char *app_icon_basedir_fullpath = malloc(strlen(app_data_dir) + strlen(app_icon_dirname) + strlen("/hicolor") + 1);
|
||||||
|
strcpy(app_icon_basedir_fullpath, app_data_dir);
|
||||||
|
strcat(app_icon_basedir_fullpath, app_icon_dirname);
|
||||||
|
strcat(app_icon_basedir_fullpath, "/hicolor");
|
||||||
|
*/
|
||||||
|
gtk_window_set_title(GTK_WINDOW(window), package_name);
|
||||||
|
gtk_window_set_default_size(GTK_WINDOW(window), d->window_width, d->window_height);
|
||||||
|
g_signal_connect(window, "close-request", G_CALLBACK (app_exit), env);
|
||||||
|
/*
|
||||||
|
GtkIconTheme *theme = gtk_icon_theme_get_for_display(gdk_display_get_default());
|
||||||
|
printf(">>%s<<\n", app_icon_basedir_fullpath);
|
||||||
|
printf(">%s<\n", app_icon_basename);
|
||||||
|
gtk_icon_theme_set_search_path(theme, (const char *const[]){app_icon_basedir_fullpath, NULL});
|
||||||
|
|
||||||
|
printf(">>>%d<<<\n", gtk_icon_theme_has_icon(theme, app_icon_basename));
|
||||||
|
|
||||||
|
gtk_window_set_icon_name(GTK_WINDOW(window), app_icon_basename);
|
||||||
|
|
||||||
|
exit(69);
|
||||||
|
*/
|
||||||
|
// free(tmp);
|
||||||
|
// free(app_icon_basedir_fullpath);
|
||||||
|
|
||||||
activity_start(env, activity_object);
|
activity_start(env, activity_object);
|
||||||
|
|
||||||
g_timeout_add(10, G_SOURCE_FUNC(hacky_on_window_focus_changed_callback), env);
|
g_timeout_add(10, G_SOURCE_FUNC(hacky_on_window_focus_changed_callback), env);
|
||||||
@@ -421,8 +457,8 @@ void init__r_debug();
|
|||||||
|
|
||||||
int main(int argc, char **argv/*, JNIEnv *env*/)
|
int main(int argc, char **argv/*, JNIEnv *env*/)
|
||||||
{
|
{
|
||||||
GtkApplication *app;
|
GtkApplication *app;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
/* this has to be done in the main executable, so might as well do it here*/
|
/* this has to be done in the main executable, so might as well do it here*/
|
||||||
init__r_debug();
|
init__r_debug();
|
||||||
@@ -436,19 +472,19 @@ int main(int argc, char **argv/*, JNIEnv *env*/)
|
|||||||
callback_data->window_width = 960;
|
callback_data->window_width = 960;
|
||||||
callback_data->window_height = 540;
|
callback_data->window_height = 540;
|
||||||
|
|
||||||
app = gtk_application_new("com.example.demo_application", G_APPLICATION_NON_UNIQUE | G_APPLICATION_HANDLES_OPEN);
|
app = gtk_application_new("com.example.demo_application", G_APPLICATION_NON_UNIQUE | G_APPLICATION_HANDLES_OPEN);
|
||||||
|
|
||||||
// cmdline related setup
|
// cmdline related setup
|
||||||
init_cmd_parameters(G_APPLICATION(app), callback_data);
|
init_cmd_parameters(G_APPLICATION(app), callback_data);
|
||||||
g_application_set_option_context_summary(G_APPLICATION(app), "a translation layer for running android applications natively on Linux");
|
g_application_set_option_context_summary(G_APPLICATION(app), "a translation layer for running android applications natively on Linux");
|
||||||
|
|
||||||
g_signal_connect(app, "activate", G_CALLBACK (activate), callback_data);
|
g_signal_connect(app, "activate", G_CALLBACK (activate), callback_data);
|
||||||
g_signal_connect(app, "open", G_CALLBACK (open), callback_data);
|
g_signal_connect(app, "open", G_CALLBACK (open), callback_data);
|
||||||
status = g_application_run(G_APPLICATION(app), argc, argv);
|
status = g_application_run(G_APPLICATION(app), argc, argv);
|
||||||
g_object_unref(app);
|
g_object_unref(app);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char dl_loader[] __attribute__((section(".interp"))) =
|
/* TODO: recall what this is doing here */
|
||||||
"/lib/ld-linux.so.2";
|
const char dl_loader[] __attribute__((section(".interp"))) = "/lib/ld-linux.so.2";
|
||||||
|
|||||||
Reference in New Issue
Block a user