summaryrefslogtreecommitdiff
path: root/navit/android.c
diff options
context:
space:
mode:
authorrikky <rikky@ffa7fe5e-494d-0410-b361-a75ebd5db220>2012-05-12 22:53:05 +0000
committerrikky <rikky@ffa7fe5e-494d-0410-b361-a75ebd5db220>2012-05-12 22:53:05 +0000
commitf86cf9fed245ebd428888783af0c0877e39029a5 (patch)
treec6fe5a8f5bc697b63a0ef8f093a1578c7c5f77e4 /navit/android.c
parent361c25f8cd482228adec560cff278ee89d0db231 (diff)
downloadnavit-f86cf9fed245ebd428888783af0c0877e39029a5.tar.gz
Fix:Android:Rewrite android search dialog handling. Fix for crashs/deadlocks and cleanup
git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit@5101 ffa7fe5e-494d-0410-b361-a75ebd5db220
Diffstat (limited to 'navit/android.c')
-rw-r--r--navit/android.c376
1 files changed, 315 insertions, 61 deletions
diff --git a/navit/android.c b/navit/android.c
index b44a6b41e..dcd0f9b3e 100644
--- a/navit/android.c
+++ b/navit/android.c
@@ -21,11 +21,23 @@
#include "start_real.h"
#include "track.h"
-
JNIEnv *jnienv;
jobject *android_activity;
int android_version;
+struct android_search_priv
+{
+ struct jni_object search_result_obj;
+ struct event_idle *idle_ev;
+ struct callback *idle_clb;
+ struct search_list *search_list;
+ struct attr search_attr;
+ gchar **phrases;
+ int current_phrase_per_level[4];
+ int partial;
+ int found;
+};
+
int
android_find_class_global(char *name, jclass *ret)
{
@@ -52,7 +64,6 @@ android_find_method(jclass class, char *name, char *args, jmethodID *ret)
JNIEXPORT void JNICALL
Java_org_navitproject_navit_Navit_NavitMain( JNIEnv* env, jobject thiz, jobject activity, jobject lang, int version, jobject display_density_string, jobject path)
{
- char *strings[]={NULL,NULL};
const char *langstr;
const char *displaydensitystr;
android_version=version;
@@ -68,10 +79,9 @@ Java_org_navitproject_navit_Navit_NavitMain( JNIEnv* env, jobject thiz, jobject
dbg(0,"*****displaydensity=%s\n",displaydensitystr);
setenv("ANDROID_DENSITY",displaydensitystr,1);
(*env)->ReleaseStringUTFChars(env, display_density_string, displaydensitystr);
- strings[0]=(*env)->GetStringUTFChars(env, path, NULL);
- main_real(1, strings);
- (*env)->ReleaseStringUTFChars(env, path, strings[0]);
-
+ const char *strings=(*env)->GetStringUTFChars(env, path, NULL);
+ main_real(1, &strings);
+ (*env)->ReleaseStringUTFChars(env, path, strings);
}
JNIEXPORT void JNICALL
@@ -153,7 +163,6 @@ Java_org_navitproject_navit_NavitWatch_WatchCallback( JNIEnv* env, jobject thiz,
callback_call_0((struct callback *)id);
}
-
JNIEXPORT void JNICALL
Java_org_navitproject_navit_NavitSensors_SensorCallback( JNIEnv* env, jobject thiz, int id, int sensor, float x, float y, float z)
{
@@ -161,62 +170,25 @@ Java_org_navitproject_navit_NavitSensors_SensorCallback( JNIEnv* env, jobject th
callback_call_4((struct callback *)id, sensor, &x, &y, &z);
}
+// type: 0=town, 1=street, 2=House#
void
-android_return_search_result(struct jni_object *jni_o, char *str)
+android_return_search_result(struct jni_object *jni_o, int type, struct pcoord *location, const char *address)
{
- jstring js2 = NULL;
- JNIEnv* env2;
- env2=jni_o->env;
- js2 = (*env2)->NewStringUTF(jni_o->env,str);
- (*env2)->CallVoidMethod(jni_o->env, jni_o->jo, jni_o->jm, js2);
- (*env2)->DeleteLocalRef(jni_o->env, js2);
+ struct coord_geo geo_location;
+ struct coord c;
+ jstring jaddress = NULL;
+ JNIEnv* env;
+ env=jni_o->env;
+ jaddress = (*env)->NewStringUTF(jni_o->env,address);
+
+ c.x=location->x;
+ c.y=location->y;
+ transform_to_geo(location->pro, &c, &geo_location);
+
+ (*env)->CallVoidMethod(jni_o->env, jni_o->jo, jni_o->jm, type, geo_location.lat, geo_location.lng, jaddress);
+ (*env)->DeleteLocalRef(jni_o->env, jaddress);
}
-JNIEXPORT void JNICALL
-Java_org_navitproject_navit_NavitGraphics_CallbackSearchResultList( JNIEnv* env, jobject thiz, int partial, jobject country, jobject str)
-{
- struct attr attr;
- const char *search_string =(*env)->GetStringUTFChars(env, str, NULL);
- dbg(0,"search '%s'\n", search_string);
-
- config_get_attr(config_get(), attr_navit, &attr, NULL);
-
- jclass cls = (*env)->GetObjectClass(env,thiz);
- jmethodID aMethodID = (*env)->GetMethodID(env, cls, "fillStringArray", "(Ljava/lang/String;)V");
- if(aMethodID != 0)
- {
- struct jni_object my_jni_object;
- GList *ret = NULL;
- struct mapset *ms4=navit_get_mapset(attr.u.navit);
- struct search_list *sl = search_list_new(ms4);
- struct attr country_attr;
- const char *str_country=(*env)->GetStringUTFChars(env, country, NULL);
-
- country_attr.type=attr_country_iso2;
- country_attr.u.str=str_country;
-
- search_list_search(sl, &country_attr, 0);
- (*env)->ReleaseStringUTFChars(env, country, str_country);
-
- my_jni_object.env=env;
- my_jni_object.jo=thiz;
- my_jni_object.jm=aMethodID;
-
- /* TODO (rikky#1#): does return nothing yet, also should use a generic callback instead of jni_object */
- ret=search_by_address(sl,search_string,partial,&my_jni_object);
- search_list_destroy(sl);
-
- dbg(0,"ret=%p\n",ret);
-
- g_list_free(ret);
- }
- else
- dbg(0,"**** Unable to get methodID: fillStringArray");
-
- (*env)->ReleaseStringUTFChars(env, str, search_string);
-}
-
-
JNIEXPORT jstring JNICALL
Java_org_navitproject_navit_NavitGraphics_CallbackLocalizedString( JNIEnv* env, jobject thiz, jobject str)
{
@@ -262,7 +234,7 @@ Java_org_navitproject_navit_NavitGraphics_CallbackMessageChannel( JNIEnv* env, j
{
struct mapset *ms = navit_get_mapset(attr.u.navit);
struct attr type, name, data, *attrs[4];
- char *map_location=(*env)->GetStringUTFChars(env, str, NULL);
+ const char *map_location=(*env)->GetStringUTFChars(env, str, NULL);
dbg(0,"*****string=%s\n",map_location);
type.type=attr_type;
type.u.str="binfile";
@@ -288,7 +260,7 @@ Java_org_navitproject_navit_NavitGraphics_CallbackMessageChannel( JNIEnv* env, j
{
struct mapset *ms = navit_get_mapset(attr.u.navit);
struct attr map_r;
- char *map_location=(*env)->GetStringUTFChars(env, str, NULL);
+ const char *map_location=(*env)->GetStringUTFChars(env, str, NULL);
struct map * delete_map = mapset_get_map_by_name(ms, map_location);
dbg(0,"delete map %s (%p)", map_location, delete_map);
@@ -486,3 +458,285 @@ Java_org_navitproject_navit_NavitGraphics_GetAllCountries( JNIEnv* env, jobject
}
return all_countries;
}
+
+static char *
+postal_str(struct search_list_result *res, int level)
+{
+ char *ret=NULL;
+ if (res->town->common.postal)
+ ret=res->town->common.postal;
+ if (res->town->common.postal_mask)
+ ret=res->town->common.postal_mask;
+ if (level == 1)
+ return ret;
+ if (res->street->common.postal)
+ ret=res->street->common.postal;
+ if (res->street->common.postal_mask)
+ ret=res->street->common.postal_mask;
+ if (level == 2)
+ return ret;
+ if (res->house_number->common.postal)
+ ret=res->house_number->common.postal;
+ if (res->house_number->common.postal_mask)
+ ret=res->house_number->common.postal_mask;
+ return ret;
+}
+
+static char *
+district_str(struct search_list_result *res, int level)
+{
+ char *ret=NULL;
+ if (res->town->common.district_name)
+ ret=res->town->common.district_name;
+ if (level == 1)
+ return ret;
+ if (res->street->common.district_name)
+ ret=res->street->common.district_name;
+ if (level == 2)
+ return ret;
+ if (res->house_number->common.district_name)
+ ret=res->house_number->common.district_name;
+ return ret;
+}
+
+static char *
+town_str(struct search_list_result *res, int level)
+{
+ char *town=res->town->common.town_name;
+ char *district=district_str(res, level);
+ char *postal=postal_str(res, level);
+ char *postal_sep=" ";
+ char *district_begin=" (";
+ char *district_end=")";
+ char *county_sep = ", Co. ";
+ char *county = res->town->common.county_name;
+ if (!postal)
+ postal_sep=postal="";
+ if (!district)
+ district_begin=district_end=district="";
+ if (!county)
+ county_sep=county="";
+
+ return g_strdup_printf("%s%s%s%s%s%s%s%s", postal, postal_sep, town, district_begin, district, district_end, county_sep, county);
+}
+
+static void
+android_search_end(struct android_search_priv *search_priv)
+{
+ dbg(1, "End search");
+ JNIEnv* env = search_priv->search_result_obj.env;
+ if (search_priv->idle_ev) {
+ event_remove_idle(search_priv->idle_ev);
+ search_priv->idle_ev=NULL;
+ }
+ if (search_priv->idle_clb) {
+ callback_destroy(search_priv->idle_clb);
+ search_priv->idle_clb=NULL;
+ }
+ jclass cls = (*env)->GetObjectClass(env,search_priv->search_result_obj.jo);
+ jmethodID finish_MethodID = (*env)->GetMethodID(env, cls, "finishAddressSearch", "()V");
+ if(finish_MethodID != 0) {
+ (*env)->CallVoidMethod(env, search_priv->search_result_obj.jo, finish_MethodID);
+ } else {
+ dbg(0, "Error method finishAddressSearch not found");
+ }
+
+ search_list_destroy(search_priv->search_list);
+ g_strfreev(search_priv->phrases);
+ g_free(search_priv);
+}
+
+static enum attr_type android_search_level[] = {
+ attr_town_or_district_name,
+ attr_street_name,
+ attr_house_number
+};
+
+static void
+android_search_idle(struct android_search_priv *search_priv)
+{
+ dbg(1, "enter android_search_idle");
+
+ struct search_list_result *res = search_list_get_result(search_priv->search_list);
+ if (res) {
+ dbg(1, "Town: %s, Street: %s\n",res->town ? res->town->common.town_name : "no town", res->street ? res->street->name : "no street");
+ search_priv->found = 1;
+ switch (search_priv->search_attr.type)
+ {
+ case attr_town_or_district_name:
+ {
+ gchar *town = town_str(res, 1);
+ android_return_search_result(&search_priv->search_result_obj, 0, res->town->common.c, town);
+ g_free(town);
+ break;
+ }
+ case attr_street_name:
+ {
+ gchar *town = town_str(res, 2);
+ gchar *address = g_strdup_printf("%.101s,%.101s, %.101s", res->country->name, town, res->street->name);
+ android_return_search_result(&search_priv->search_result_obj, 1, res->street->common.c, address);
+ g_free(address);
+ g_free(town);
+ break;
+ }
+ case attr_house_number:
+ {
+ gchar *town = town_str(res, 3);
+ gchar *address = g_strdup_printf("%.101s, %.101s, %.101s %.15s", res->country->name, town, res->street->name, res->house_number->house_number);
+ android_return_search_result(&search_priv->search_result_obj, 2, res->house_number->common.c, address);
+ g_free(address);
+ g_free(town);
+ break;
+ }
+ default:
+ dbg(0, "Unhandled search type %d", search_priv->search_attr.type);
+ }
+ } else {
+ int level = search_list_level(search_priv->search_attr.type) - 1;
+
+ if (search_priv->found) {
+ search_priv->found = 0;
+ if (search_priv->search_attr.type != attr_house_number) {
+ level++;
+ }
+ }
+ dbg(2, "test phrase: %d,%d, %d, level %d", search_priv->current_phrase_per_level[0], search_priv->current_phrase_per_level[1], search_priv->current_phrase_per_level[2] , level)
+ do {
+ while (!search_priv->phrases[++search_priv->current_phrase_per_level[level]]) {
+ dbg(2, "next phrase: %d,%d, %d, level %d", search_priv->current_phrase_per_level[0], search_priv->current_phrase_per_level[1], search_priv->current_phrase_per_level[2] , level)
+ if (level > 0) {
+ search_priv->current_phrase_per_level[level] = -1;
+ level--;
+ } else {
+ android_search_end(search_priv);
+ return;
+ }
+ }
+ } while (level > 0 ? search_priv->current_phrase_per_level[level] == search_priv->current_phrase_per_level[level-1] : 0);
+ dbg(2, "used phrase: %d,%d, %d, level %d, '%s'", search_priv->current_phrase_per_level[0], search_priv->current_phrase_per_level[1], search_priv->current_phrase_per_level[2] , level, attr_to_name(android_search_level[level]))
+ dbg(1, "Search for '%s'", search_priv->phrases[search_priv->current_phrase_per_level[level]]);
+ search_priv->search_attr.type = android_search_level[level];
+ search_priv->search_attr.u.str = search_priv->phrases[search_priv->current_phrase_per_level[level]];
+ struct attr test;
+ test.type = android_search_level[level];
+ test.u.str = search_priv->phrases[search_priv->current_phrase_per_level[level]];
+ search_list_search(search_priv->search_list, &test, search_priv->partial);
+ }
+ dbg(2, "leave");
+}
+
+static char *
+search_fix_spaces(const char *str)
+{
+ int i;
+ int len=strlen(str);
+ char c,*s,*d,*ret=g_strdup(str);
+
+ for (i = 0 ; i < len ; i++) {
+ if (ret[i] == ',' || ret[i] == ',' || ret[i] == '/')
+ ret[i]=' ';
+ }
+ s=ret;
+ d=ret;
+ len=0;
+ do {
+ c=*s++;
+ if (c != ' ' || len != 0) {
+ *d++=c;
+ len++;
+ }
+ while (c == ' ' && *s == ' ')
+ s++;
+ if (c == ' ' && *s == '\0') {
+ d--;
+ len--;
+ }
+ } while (c);
+ return ret;
+}
+
+static void start_search(struct android_search_priv *search_priv, const char *search_string)
+{
+ dbg(1,"enter %s\n", search_string);
+ char *str=search_fix_spaces(search_string);
+ search_priv->phrases = g_strsplit(str, " ", 0);
+ //ret=search_address_town(ret, sl, phrases, NULL, partial, jni);
+
+ dbg(1,"First search phrase %s", search_priv->phrases[0]);
+ search_priv->search_attr.u.str= search_priv->phrases[0];
+ search_priv->search_attr.type=attr_town_or_district_name;
+ search_list_search(search_priv->search_list, &search_priv->search_attr, search_priv->partial);
+
+ search_priv->idle_clb = callback_new_1(callback_cast(android_search_idle), search_priv);
+ search_priv->idle_ev = event_add_idle(50,search_priv->idle_clb);
+ //callback_call_0(search_priv->idle_clb);
+
+ g_free(str);
+ dbg(1,"leave\n");
+}
+
+JNIEXPORT jlong JNICALL
+Java_org_navitproject_navit_NavitAddressSearchActivity_CallbackStartAddressSearch( JNIEnv* env, jobject thiz, int partial, jobject country, jobject str)
+{
+ struct attr attr;
+ const char *search_string =(*env)->GetStringUTFChars(env, str, NULL);
+ dbg(0,"search '%s'\n", search_string);
+
+ config_get_attr(config_get(), attr_navit, &attr, NULL);
+
+ jclass cls = (*env)->GetObjectClass(env,thiz);
+ jmethodID aMethodID = (*env)->GetMethodID(env, cls, "receiveAddress", "(IFFLjava/lang/String;)V");
+ struct android_search_priv *search_priv = NULL;
+
+ if(aMethodID != 0)
+ {
+ struct mapset *ms4=navit_get_mapset(attr.u.navit);
+ struct attr country_attr;
+ const char *str_country=(*env)->GetStringUTFChars(env, country, NULL);
+ struct search_list_result *slr;
+ int count = 0;
+
+ search_priv = g_new0( struct android_search_priv, 1);
+ search_priv->search_list = search_list_new(ms4);
+ search_priv->partial = partial;
+ search_priv->current_phrase_per_level[1] = -1;
+ search_priv->current_phrase_per_level[2] = -1;
+
+ country_attr.type=attr_country_iso2;
+ country_attr.u.str=g_strdup(str_country);
+ search_list_search(search_priv->search_list, &country_attr, 0);
+
+ while ((slr=search_list_get_result(search_priv->search_list)))
+ {
+ count++;
+ }
+ if (!count)
+ dbg(0,"Country not found");
+
+ dbg(1,"search in country '%s'\n", str_country);
+ (*env)->ReleaseStringUTFChars(env, country, str_country);
+
+ search_priv->search_result_obj.env = env;
+ search_priv->search_result_obj.jo = (*env)->NewGlobalRef(env, thiz);
+ search_priv->search_result_obj.jm = aMethodID;
+
+ start_search(search_priv, search_string);
+ }
+ else
+ dbg(0,"**** Unable to get methodID: fillStringArray");
+
+ (*env)->ReleaseStringUTFChars(env, str, search_string);
+
+ return (jlong)(long)search_priv;
+}
+
+JNIEXPORT void JNICALL
+Java_org_navitproject_navit_NavitAddressSearchActivity_CallbackCancelAddressSearch( JNIEnv* env, jobject thiz, jlong handle)
+{
+ struct android_search_priv *priv = (void*)(long)handle;
+
+ if (priv)
+ android_search_end(priv);
+ else
+ dbg(0, "Error: Cancel search failed");
+}