diff options
| author | rikky <rikky@ffa7fe5e-494d-0410-b361-a75ebd5db220> | 2012-05-12 22:53:05 +0000 |
|---|---|---|
| committer | rikky <rikky@ffa7fe5e-494d-0410-b361-a75ebd5db220> | 2012-05-12 22:53:05 +0000 |
| commit | f86cf9fed245ebd428888783af0c0877e39029a5 (patch) | |
| tree | c6fe5a8f5bc697b63a0ef8f093a1578c7c5f77e4 /navit/android.c | |
| parent | 361c25f8cd482228adec560cff278ee89d0db231 (diff) | |
| download | navit-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.c | 376 |
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"); +} |
