Added local experts JNI

This commit is contained in:
r.kuznetsov 2017-10-24 15:56:56 +03:00 committed by Aleksandr Zatsepin
parent 0241aedd3d
commit 500cefe59f
7 changed files with 251 additions and 33 deletions

View file

@ -87,6 +87,7 @@ LOCAL_SRC_FILES := \
com/mapswithme/maps/editor/Editor.cpp \
com/mapswithme/maps/editor/OsmOAuth.cpp \
com/mapswithme/maps/Framework.cpp \
com/mapswithme/maps/locals/Locals.cpp \
com/mapswithme/maps/LocationState.cpp \
com/mapswithme/maps/LocationHelper.cpp \
com/mapswithme/maps/MapFragment.cpp \

View file

@ -614,6 +614,20 @@ int Framework::ToDoAfterUpdate() const
return (int) m_work.ToDoAfterUpdate();
}
uint64_t Framework::GetLocals(JNIEnv * env, jobject policy, double lat, double lon,
locals::LocalsSuccessCallback const & successFn,
locals::LocalsErrorCallback const & errorFn)
{
auto api = NativeFramework()->GetLocalsApi(ToNativeNetworkPolicy(env, policy));
if (api == nullptr)
return 0;
std::string const langStr = languages::GetCurrentNorm();
size_t constexpr kResultsOnPage = 5;
size_t constexpr kPageNumber = 1;
return api->GetLocals(lat, lon, langStr, kResultsOnPage, kPageNumber, successFn, errorFn);
}
void Framework::LogLocalAdsEvent(local_ads::EventType type, double lat, double lon, uint16_t accuracy)
{
auto const & info = g_framework->GetPlacePageInfo();

View file

@ -16,6 +16,8 @@
#include "local_ads/event.hpp"
#include "partners_api/locals_api.hpp"
#include "platform/country_defines.hpp"
#include "platform/location.hpp"
@ -210,6 +212,10 @@ namespace android
int ToDoAfterUpdate() const;
uint64_t GetLocals(JNIEnv * env, jobject policy, double lat, double lon,
locals::LocalsSuccessCallback const & successFn,
locals::LocalsErrorCallback const & errorFn);
void LogLocalAdsEvent(local_ads::EventType event, double lat, double lon, uint16_t accuracy);
};
}

View file

@ -1,32 +1,116 @@
#include "android/jni/com/mapswithme/core/jni_helper.hpp"
#include "android/jni/com/mapswithme/maps/Framework.hpp"
#include "android/jni/com/mapswithme/core/jni_helper.hpp"
#include "partners_api/locals_api.hpp"
#include <string>
#include <vector>
namespace
{
jclass g_localsClass = nullptr;
jobject g_localsInstance;
jmethodID g_onLocalsReceivedMethod;
jmethodID g_onLocalsErrorReceivedMethod;
jclass g_localExpertClass;
jmethodID g_localExpertConstructor;
jclass g_localErrorClass;
jmethodID g_localErrorConstructor;
uint64_t g_lastRequestId = 0;
void PrepareClassRefs(JNIEnv * env)
{
if (g_localExpertClass)
if (g_localsClass != nullptr)
return;
@NonNull int id,
@NotNull String name,
@NotNull String country,
@NotNull String city,
double rating, int reviewCount, @NonNull double price
@NonNull String currency, String motto, String about,
@NonNull String offer, @NonNull String pageUrl, @NonNull String photoUrl
g_localsClass = jni::GetGlobalClassRef(env, "com/mapswithme/maps/locals/Locals");
static jfieldID const localsInstanceField = jni::GetStaticFieldID(env, g_localsClass, "INSTANCE",
"Lcom/mapswithme/maps/locals/Locals;");
g_localsInstance = env->GetStaticObjectField(g_localsClass, localsInstanceField);
g_onLocalsReceivedMethod = jni::GetMethodID(env, g_localsInstance, "onLocalsReceived",
"([Lcom/mapswithme/maps/locals/LocalExpert;)V");
g_onLocalsErrorReceivedMethod = jni::GetMethodID(env, g_localsInstance,
"onLocalsErrorReceived",
"(Lcom/mapswithme/maps/locals/LocalsError;)V");
// int id, @NonNull String name, @NonNull String country,
// @NonNull String city, double rating, int reviewCount,
// double price, @NonNull String currency, @NonNull String motto,
// @NonNull String about, @NonNull String offer, @NonNull String pageUrl,
// @NonNull String photoUrl
g_localExpertClass = jni::GetGlobalClassRef(env, "com/mapswithme/maps/locals/LocalExpert");
g_localExpertConstructor =
jni::GetConstructorID(env, g_viatorProductClass,
jni::GetConstructorID(env, g_localExpertClass,
"(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;DID"
"Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;"
"Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
// @ErrorCode int code, @NonNull String message
g_localErrorClass = jni::GetGlobalClassRef(env, "com/mapswithme/maps/locals/LocalError");
g_localErrorConstructor = jni::GetConstructorID(env, g_localErrorClass,
"(ILjava/lang/String;)V");
}
void OnLocalsSuccess(uint64_t requestId, std::vector<locals::LocalExpert> const & locals,
size_t pageNumber, size_t countPerPage, bool hasPreviousPage,
bool hasNextPage)
{
if (g_lastRequestId != requestId)
return;
JNIEnv * env = jni::GetEnv();
auto const localExpertBuilder = [](JNIEnv * env, locals::LocalExpert const & expert)
{
jni::TScopedLocalRef jName(env, jni::ToJavaString(env, expert.m_name));
jni::TScopedLocalRef jCountry(env, jni::ToJavaString(env, expert.m_country));
jni::TScopedLocalRef jCity(env, jni::ToJavaString(env, expert.m_city));
jni::TScopedLocalRef jCurrency(env, jni::ToJavaString(env, expert.m_currency));
jni::TScopedLocalRef jMotto(env, jni::ToJavaString(env, expert.m_motto));
jni::TScopedLocalRef jAboutExpert(env, jni::ToJavaString(env, expert.m_aboutExpert));
jni::TScopedLocalRef jOfferDescription(env, jni::ToJavaString(env, expert.m_offerDescription));
jni::TScopedLocalRef jPageUrl(env, jni::ToJavaString(env, expert.m_pageUrl));
jni::TScopedLocalRef jPhotoUrl(env, jni::ToJavaString(env, expert.m_photoUrl));
return env->NewObject(g_localExpertClass, g_localExpertConstructor,
expert.m_id, jName.get(), jCountry.get(), jCity.get(),
expert.m_rating, expert.m_reviewCount, expert.m_pricePerHour,
jCurrency.get(), jMotto.get(), jAboutExpert.get(),
jOfferDescription.get(), jPageUrl.get(), jPhotoUrl.get());
};
jni::TScopedLocalObjectArrayRef jLocals(env, jni::ToJavaArray(env, g_localExpertClass, locals,
localExpertBuilder));
env->CallVoidMethod(g_localsInstance, g_onLocalsReceivedMethod, jLocals.get());
jni::HandleJavaException(env);
}
void OnLocalsError(uint64_t requestId, int errorCode, std::string const & errorMessage)
{
if (g_lastRequestId != requestId)
return;
JNIEnv * env = jni::GetEnv();
jni::TScopedLocalRef errorStr(env, jni::ToJavaString(env, errorMessage));
jni::TScopedLocalRef errorObj(env, env->NewObject(g_localErrorClass, g_localErrorConstructor,
errorCode, errorStr.get()));
env->CallVoidMethod(g_localsInstance, g_onLocalsErrorReceivedMethod, errorObj.get());
jni::HandleJavaException(env);
}
} // namespace
extern "C" {
JNIEXPORT void JNICALL
Java_com_mapswithme_maps_locals_Locals_nativeRequestLocals(JNIEnv * env, jclass clazz,
jobject policy, jdouble lat,
jdouble lon)
{
PrepareClassRefs(env);
g_lastRequestId = g_framework->GetLocals(env, policy, lat, lon, &OnLocalsSuccess,
&OnLocalsError);
}
} // extern "C"

View file

@ -5,7 +5,7 @@ import android.os.Parcelable;
import android.support.annotation.NonNull;
public final class LocalExpert implements Parcelable
final class LocalExpert implements Parcelable
{
private final int mId;
@NonNull
@ -104,10 +104,7 @@ public final class LocalExpert implements Parcelable
}
@Override
public int describeContents()
{
return 0;
}
public int describeContents() { return 0; }
int getId() { return mId; }
@ -122,15 +119,9 @@ public final class LocalExpert implements Parcelable
double getRating() { return mRating; }
int getReviewCount()
{
return mReviewCount;
}
int getReviewCount() { return mReviewCount; }
double getPrice()
{
return mPrice;
}
double getPrice() { return mPrice; }
@NonNull
String getCurrency() { return mCurrency; }
@ -145,10 +136,7 @@ public final class LocalExpert implements Parcelable
String getOfferDescription() { return mOfferDescription; }
@NonNull
String getPageUrl()
{
return mPageUrl;
}
String getPageUrl() { return mPageUrl;}
@NonNull
String getPhotoUrl() { return mPhotoUrl; }
@ -162,17 +150,40 @@ public final class LocalExpert implements Parcelable
LocalExpert that = (LocalExpert) o;
if (mId != that.mId) return false;
if (!mName.equals(that.mName)) return false;
if (!mCountry.equals(that.mCountry)) return false;
if (!mCity.equals(that.mCity)) return false;
if (Double.compare(that.mRating, mRating) != 0) return false;
if (mReviewCount != that.mReviewCount) return false;
if (Double.compare(that.mPrice, mPrice) != 0) return false;
if (!mName.equals(that.mName)) return false;
if (!mCountry.equals(that.mCountry)) return false;
if (!mCity.equals(that.mCity)) return false;
if (!mCurrency.equals(that.mCurrency)) return false;
if (!mMotto.equals(that.mMotto)) return false;
if (!mAboutExpert.equals(that.mAboutExpert)) return false;
if (!mOfferDescription.equals(that.mOfferDescription)) return false;
if (!mPhotoUrl.equals(that.mPhotoUrl)) return false;
return mPageUrl.equals(that.mPageUrl);
if (!mPageUrl.equals(that.mPageUrl)) return false;
return mPhotoUrl.equals(that.mPhotoUrl);
}
@Override
public int hashCode()
{
int result;
long temp;
result = mId;
result = 31 * result + mName.hashCode();
result = 31 * result + mCountry.hashCode();
result = 31 * result + mCity.hashCode();
temp = Double.doubleToLongBits(mRating);
result = 31 * result + (int) (temp ^ (temp >>> 32));
result = 31 * result + mReviewCount;
temp = Double.doubleToLongBits(mPrice);
result = 31 * result + (int) (temp ^ (temp >>> 32));
result = 31 * result + mCurrency.hashCode();
result = 31 * result + mMotto.hashCode();
result = 31 * result + mAboutExpert.hashCode();
result = 31 * result + mOfferDescription.hashCode();
result = 31 * result + mPageUrl.hashCode();
result = 31 * result + mPhotoUrl.hashCode();
return result;
}
}

View file

@ -0,0 +1,54 @@
package com.mapswithme.maps.locals;
import android.support.annotation.MainThread;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.mapswithme.util.NetworkPolicy;
import com.mapswithme.util.concurrency.UiThread;
final class Locals
{
public static final Locals INSTANCE = new Locals();
@Nullable
private LocalsListener mListener;
private Locals() {}
public void setLocalsListener(@Nullable LocalsListener listener)
{
mListener = listener;
}
public native void nativeRequestLocals(@NonNull NetworkPolicy policy,
double lat, double lon);
// Called from JNI.
@MainThread
void onLocalsReceived(@NonNull LocalExpert[] experts)
{
if (!UiThread.currentThreadIsUi())
throw new AssertionError("Must be called from UI thread!");
if (mListener != null)
mListener.onLocalsReceived(experts);
}
// Called from JNI.
@MainThread
void onLocalsErrorReceived(@NonNull LocalsError error)
{
if (!UiThread.currentThreadIsUi())
throw new AssertionError("Must be called from UI thread!");
if (mListener != null)
mListener.onLocalsErrorReceived(error);
}
public interface LocalsListener
{
void onLocalsReceived(@NonNull LocalExpert[] experts);
void onLocalsErrorReceived(@NonNull LocalsError error);
}
}

View file

@ -0,0 +1,48 @@
package com.mapswithme.maps.locals;
import android.support.annotation.IntDef;
import android.support.annotation.NonNull;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
class LocalsError
{
static final int UNKNOWN_ERROR = 0;
@Retention(RetentionPolicy.SOURCE)
@IntDef({ UNKNOWN_ERROR })
@interface ErrorCode {}
@ErrorCode
private final int mCode;
@NonNull
private final String mMessage;
public LocalsError(@ErrorCode int code, @NonNull String message)
{
mCode = code;
mMessage = message;
}
@ErrorCode
public int getCode()
{
return mCode;
}
@NonNull
public String getMessage()
{
return mMessage;
}
@Override
public String toString()
{
return "LocalsError{" +
"mCode=" + mCode +
", mMessage=" + mMessage +
'}';
}
}