Merge pull request #2899 from yunikkk/fixes

[android] UI fixes; OSM username instead of profile.
This commit is contained in:
Alexander Marchuk 2016-04-15 18:51:45 +03:00
commit 1a8408b2e6
17 changed files with 325 additions and 459 deletions

View file

@ -15,22 +15,18 @@ extern "C"
if (items.empty())
return;
static jclass const pairClass = static_cast<jclass>(env->NewGlobalRef(env->FindClass("android/util/Pair")));
static jmethodID const pairCtor = env->GetMethodID(pairClass, "<init>", "(Ljava/lang/Object;Ljava/lang/Object;)V");
static jmethodID const listAddMethod = env->GetMethodID(env->GetObjectClass(result), "add", "(Ljava/lang/Object;)Z");
static jclass const pairClass = jni::GetGlobalClassRef(env, "android/util/Pair");
static jmethodID const pairCtor = jni::GetConstructorID(env, pairClass, "(Ljava/lang/Object;Ljava/lang/Object;)V");
static jmethodID const listAddMethod = jni::GetMethodID(env, result, "add", "(Ljava/lang/Object;)Z");
for (TSearchRequest const & item : items)
{
jstring locale = jni::ToJavaString(env, item.first.c_str());
jstring query = jni::ToJavaString(env, item.second.c_str());
jobject pair = env->NewObject(pairClass, pairCtor, locale, query);
ASSERT(pair, (jni::DescribeException()));
jni::TScopedLocalRef locale(env, jni::ToJavaString(env, item.first.c_str()));
jni::TScopedLocalRef query(env, jni::ToJavaString(env, item.second.c_str()));
jni::TScopedLocalRef pair(env, env->NewObject(pairClass, pairCtor, locale.get(), query.get()));
ASSERT(pair.get(), (jni::DescribeException()));
env->CallBooleanMethod(result, listAddMethod, pair);
env->DeleteLocalRef(locale);
env->DeleteLocalRef(query);
env->DeleteLocalRef(pair);
env->CallBooleanMethod(result, listAddMethod, pair.get());
}
}

View file

@ -105,8 +105,8 @@ Java_com_mapswithme_maps_bookmarks_data_BookmarkCategory_nativeGetTrack(
ASSERT(nTrack, ("Track must not be null with index:)", bmkId));
string formattedLenght;
MeasurementUtils::FormatDistance(nTrack->GetLengthMeters(), formattedLenght);
string formattedLength;
MeasurementUtils::FormatDistance(nTrack->GetLengthMeters(), formattedLength);
dp::Color nColor = nTrack->GetColor(0);
@ -117,6 +117,6 @@ Java_com_mapswithme_maps_bookmarks_data_BookmarkCategory_nativeGetTrack(
return env->NewObject(trackClazz, cId,
bmkId, id, jni::ToJavaString(env, nTrack->GetName()),
jni::ToJavaString(env, formattedLenght), androidColor);
jni::ToJavaString(env, formattedLength), androidColor);
}
} // extern "C"

View file

@ -227,7 +227,6 @@ Java_com_mapswithme_maps_editor_Editor_nativeHasWifi(JNIEnv *, jclass)
return g_editableMapObject.GetMetadata().Get(feature::Metadata::FMD_INTERNET) == "wlan";
}
JNIEXPORT jboolean JNICALL
Java_com_mapswithme_maps_editor_Editor_nativeHasSomethingToUpload(JNIEnv * env, jclass clazz)
{

View file

@ -68,9 +68,8 @@ jobjectArray JavaTimespans(JNIEnv * env, vector<Timespan> const & spans)
jobjectArray const result = env->NewObjectArray(size, g_clazzTimespan, 0);
for (int i = 0; i < size; i++)
{
jobject const jSpan = JavaTimespan(env, spans[i]);
env->SetObjectArrayElement(result, i, jSpan);
env->DeleteLocalRef(jSpan);
jni::TScopedLocalRef jSpan(env, JavaTimespan(env, spans[i]));
env->SetObjectArrayElement(result, i, jSpan.get());
}
return result;
@ -109,9 +108,8 @@ jobjectArray JavaTimetables(JNIEnv * env, TimeTableSet & tts)
jobjectArray const result = env->NewObjectArray(size, g_clazzTimetable, 0);
for (int i = 0; i < size; i++)
{
jobject const jTable = JavaTimetable(env, tts.Get(i));
env->SetObjectArrayElement(result, i, jTable);
env->DeleteLocalRef(jTable);
jni::TScopedLocalRef jTable(env, JavaTimetable(env, tts.Get(i)));
env->SetObjectArrayElement(result, i, jTable.get());
}
return result;
@ -149,12 +147,9 @@ TimeTable NativeTimetable(JNIEnv * env, jobject jTimetable)
size = env->GetArrayLength(jClosedSpans);
for (int i = 0; i < size; i++)
{
jobject const jSpan = env->GetObjectArrayElement(jClosedSpans, i);
if (jSpan)
{
tt.AddExcludeTime(NativeTimespan(env, jSpan));
env->DeleteLocalRef(jSpan);
}
jni::TScopedLocalRef jSpan(env, env->GetObjectArrayElement(jClosedSpans, i));
if (jSpan.get())
tt.AddExcludeTime(NativeTimespan(env, jSpan.get()));
}
return tt;
}
@ -168,9 +163,8 @@ TimeTableSet NativeTimetableSet(JNIEnv * env, jobjectArray jTimetables)
for (int i = 1; i < size; i++)
{
jobject const timetable = env->GetObjectArrayElement(jTimetables, i);
tts.Append(NativeTimetable(env, timetable));
env->DeleteLocalRef(timetable);
jni::TScopedLocalRef timetable(env, env->GetObjectArrayElement(jTimetables, i));
tts.Append(NativeTimetable(env, timetable.get()));
}
return tts;

View file

@ -3,7 +3,9 @@
#include "com/mapswithme/core/jni_helper.hpp"
#include "base/logging.hpp"
#include "editor/osm_auth.hpp"
#include "editor/server_api.hpp"
namespace
{
@ -97,4 +99,20 @@ Java_com_mapswithme_maps_editor_OsmOAuth_nativeGetGoogleAuthUrl(JNIEnv * env, jc
return nullptr;
}
}
JNIEXPORT jstring JNICALL
Java_com_mapswithme_maps_editor_OsmOAuth_nativeGetOsmUsername(JNIEnv * env, jclass clazz, jstring token, jstring secret)
{
try
{
TKeySecret keySecret(jni::ToNativeString(env, token), jni::ToNativeString(env, secret));
ServerApi06 const api(OsmOAuth::ServerAuth(keySecret));
return jni::ToJavaString(env, api.GetUserPreferences().m_displayName);
}
catch (exception const & ex)
{
LOG(LWARNING, ("Can't load user preferences from server: ", ex.what()));
return nullptr;
}
}
} // extern "C"

View file

@ -1,8 +1,7 @@
#include "platform/http_thread_callback.hpp"
#include "Platform.hpp"
#include "../core/jni_helper.hpp"
#include "Platform.hpp"
#include "platform/http_thread_callback.hpp"
class HttpThread
{
@ -17,64 +16,48 @@ public:
int64_t expectedFileSize,
string const & pb)
{
/// should create java object here.
JNIEnv * env = jni::GetEnv();
ASSERT ( env, () );
jclass klass = env->FindClass("com/mapswithme/maps/downloader/ChunkTask");
ASSERT ( klass, () );
static jmethodID initMethodId = env->GetMethodID(klass, "<init>", "(JLjava/lang/String;JJJ[BLjava/lang/String;)V");
ASSERT ( initMethodId, () );
static jclass const klass = jni::GetGlobalClassRef(env, "com/mapswithme/maps/downloader/ChunkTask");
// public ChunkTask(long httpCallbackID, String url, long beg, long end,
// long expectedFileSize, byte[] postBody, String userAgent)
static jmethodID const initMethodId = jni::GetConstructorID(env, klass, "(JLjava/lang/String;JJJ[BLjava/lang/String;)V");
static jmethodID const startMethodId = env->GetMethodID(klass, "start", "()V");
// User id is always the same, so do not waste time on every chunk call
static string uniqueUserId = GetPlatform().UniqueClientId();
static string const uniqueUserId = GetPlatform().UniqueClientId();
jbyteArray postBody = 0;
jni::TScopedLocalByteArrayRef postBody(env, nullptr);
size_t const postBodySize = pb.size();
if (postBodySize)
{
postBody = env->NewByteArray(postBodySize);
env->SetByteArrayRegion(postBody, 0, postBodySize, reinterpret_cast<jbyte const *>(pb.c_str()));
postBody.reset(env->NewByteArray(postBodySize));
env->SetByteArrayRegion(postBody.get(), 0, postBodySize, reinterpret_cast<jbyte const *>(pb.c_str()));
}
jstring jUrl = env->NewStringUTF(url.c_str());
jstring jUserId = env->NewStringUTF(uniqueUserId.c_str());
jobject const localSelf = env->NewObject(klass,
initMethodId,
reinterpret_cast<jlong>(&cb),
jUrl,
static_cast<jlong>(beg),
static_cast<jlong>(end),
static_cast<jlong>(expectedFileSize),
postBody,
jUserId);
m_self = env->NewGlobalRef(localSelf);
ASSERT ( m_self, () );
env->DeleteLocalRef(localSelf);
env->DeleteLocalRef(postBody);
env->DeleteLocalRef(jUrl);
env->DeleteLocalRef(jUserId);
static jmethodID startMethodId = env->GetMethodID(klass, "start", "()V");
ASSERT ( startMethodId, () );
env->DeleteLocalRef(klass);
jni::TScopedLocalRef jUrl(env, jni::ToJavaString(env, url.c_str()));
jni::TScopedLocalRef jUserId(env, jni::ToJavaString(env, uniqueUserId.c_str()));
jni::TScopedLocalRef localSelf(env, env->NewObject(klass,
initMethodId,
reinterpret_cast<jlong>(&cb),
jUrl.get(),
static_cast<jlong>(beg),
static_cast<jlong>(end),
static_cast<jlong>(expectedFileSize),
postBody.get(),
jUserId.get()));
m_self = env->NewGlobalRef(localSelf.get());
ASSERT(m_self, ());
env->CallVoidMethod(m_self, startMethodId);
jni::DumpDalvikReferenceTables();
}
~HttpThread()
{
JNIEnv * env = jni::GetEnv();
ASSERT ( env, () );
jmethodID methodId = jni::GetMethodID(env, m_self, "cancel", "(Z)Z");
ASSERT ( methodId, () );
env->CallBooleanMethod(m_self, methodId, false);
env->DeleteGlobalRef(m_self);
}
};
@ -100,22 +83,22 @@ namespace downloader
extern "C"
{
JNIEXPORT jboolean JNICALL
Java_com_mapswithme_maps_downloader_ChunkTask_nativeOnWrite(JNIEnv * env, jclass clazz, jlong httpCallbackID, jlong beg, jbyteArray data, jlong size)
{
downloader::IHttpThreadCallback * cb = reinterpret_cast<downloader::IHttpThreadCallback*>(httpCallbackID);
jbyte * buf = env->GetByteArrayElements(data, 0);
ASSERT ( buf, () );
JNIEXPORT jboolean JNICALL
Java_com_mapswithme_maps_downloader_ChunkTask_nativeOnWrite(JNIEnv * env, jclass clazz, jlong httpCallbackID, jlong beg, jbyteArray data, jlong size)
{
downloader::IHttpThreadCallback * cb = reinterpret_cast<downloader::IHttpThreadCallback*>(httpCallbackID);
jbyte * buf = env->GetByteArrayElements(data, 0);
ASSERT(buf, ());
bool const ret = cb->OnWrite(beg, buf, size);
env->ReleaseByteArrayElements(data, buf, 0);
return ret;
}
JNIEXPORT void JNICALL
Java_com_mapswithme_maps_downloader_ChunkTask_nativeOnFinish(JNIEnv * env, jclass clazz, jlong httpCallbackID, jlong httpCode, jlong beg, jlong end)
{
downloader::IHttpThreadCallback * cb = reinterpret_cast<downloader::IHttpThreadCallback*>(httpCallbackID);
cb->OnFinish(httpCode, beg, end);
}
bool const ret = cb->OnWrite(beg, buf, size);
env->ReleaseByteArrayElements(data, buf, 0);
return ret;
}
JNIEXPORT void JNICALL
Java_com_mapswithme_maps_downloader_ChunkTask_nativeOnFinish(JNIEnv * env, jclass clazz, jlong httpCallbackID, jlong httpCode, jlong beg, jlong end)
{
downloader::IHttpThreadCallback * cb = reinterpret_cast<downloader::IHttpThreadCallback*>(httpCallbackID);
cb->OnFinish(httpCode, beg, end);
}
} // extern "C"

View file

@ -25,6 +25,7 @@
android:layout_marginStart="@dimen/margin_half"
android:background="?circleAccent"
android:scaleType="center"
android:tint="?cardBackground"
tools:src="@drawable/ic_device"/>
<LinearLayout

View file

@ -197,7 +197,6 @@ public class Framework
public static native void nativeZoomToPoint(double lat, double lon, int zoom, boolean animate);
public static native void nativeTurnChoosePositionMode(boolean turnedOn);
public static native boolean nativeIsDownloadedMapAtScreenCenter();

View file

@ -194,9 +194,6 @@ public class MwmActivity extends BaseMwmFragmentActivity
private void runTasks()
{
// Task are not UI-thread bounded,
// if any task need UI-thread it should implicitly
// use Activity.runOnUiThread().
while (!mTasks.isEmpty())
mTasks.pop().run(this);
}

View file

@ -1,29 +1,18 @@
package com.mapswithme.maps.editor;
import android.content.Intent;
import android.net.Uri;
import android.net.UrlQuerySanitizer;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.annotation.Size;
import android.support.v7.app.AlertDialog;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import com.mapswithme.maps.R;
import com.mapswithme.maps.base.BaseMwmDialogFragment;
import com.mapswithme.maps.widget.InputWebView;
import com.mapswithme.util.Constants;
import com.mapswithme.util.concurrency.ThreadPool;
import com.mapswithme.util.concurrency.UiThread;
import com.mapswithme.util.statistics.Statistics;
// TODO refactor together with with AuthFragment and BaseAuthFragment to avoid code duplication
public class AuthDialogFragment extends BaseMwmDialogFragment implements View.OnClickListener
public class AuthDialogFragment extends BaseMwmDialogFragment
{
private OsmAuthFragmentDelegate mOsmAuthDelegate;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)
@ -41,162 +30,7 @@ public class AuthDialogFragment extends BaseMwmDialogFragment implements View.On
public void onViewCreated(View view, @Nullable Bundle savedInstanceState)
{
super.onViewCreated(view, savedInstanceState);
view.findViewById(R.id.login_osm).setOnClickListener(this);
view.findViewById(R.id.login_facebook).setOnClickListener(this);
view.findViewById(R.id.login_google).setOnClickListener(this);
view.findViewById(R.id.register).setOnClickListener(this);
}
@Override
public void onClick(View v)
{
// TODO show/hide spinners
switch (v.getId())
{
case R.id.login_osm:
Statistics.INSTANCE.trackAuthRequest(OsmOAuth.AuthType.OSM);
loginOsm();
break;
case R.id.login_facebook:
Statistics.INSTANCE.trackAuthRequest(OsmOAuth.AuthType.FACEBOOK);
loginWebview(OsmOAuth.AuthType.FACEBOOK);
break;
case R.id.login_google:
Statistics.INSTANCE.trackAuthRequest(OsmOAuth.AuthType.GOOGLE);
loginWebview(OsmOAuth.AuthType.GOOGLE);
break;
case R.id.lost_password:
Statistics.INSTANCE.trackEvent(Statistics.EventName.EDITOR_LOST_PASSWORD);
recoverPassword();
break;
case R.id.register:
Statistics.INSTANCE.trackEvent(Statistics.EventName.EDITOR_REG_REQUEST);
register();
break;
}
}
protected void loginOsm()
{
startActivity(new Intent(getActivity(), OsmAuthActivity.class));
dismiss();
}
protected void loginWebview(final OsmOAuth.AuthType type)
{
final WebView webview = new InputWebView(getActivity());
final AlertDialog dialog = new AlertDialog.Builder(getActivity()).setView(webview).create();
ThreadPool.getWorker().execute(new Runnable()
{
@Override
public void run()
{
final String[] auth = (type == OsmOAuth.AuthType.FACEBOOK) ? OsmOAuth.nativeGetFacebookAuthUrl()
: OsmOAuth.nativeGetGoogleAuthUrl();
UiThread.run(new Runnable()
{
@Override
public void run()
{
if (isAdded())
loadWebviewAuth(dialog, webview, auth, type);
}
});
}
});
dialog.show();
}
protected void loadWebviewAuth(final AlertDialog dialog, final WebView webview, @Size(3) final String[] auth, final OsmOAuth.AuthType type)
{
if (auth == null)
{
// TODO show some dialog
return;
}
final String authUrl = auth[0];
webview.setWebViewClient(new WebViewClient()
{
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
{
if (OsmOAuth.shouldReloadWebviewUrl(url))
{
webview.loadUrl(authUrl);
}
else if (url.contains(OsmOAuth.URL_PARAM_VERIFIER))
{
finishWebviewAuth(auth[1], auth[2], getVerifierFromUrl(url), type);
dialog.cancel();
return true;
}
return false;
}
private String getVerifierFromUrl(String authUrl)
{
UrlQuerySanitizer sanitizer = new UrlQuerySanitizer();
sanitizer.setAllowUnregisteredParamaters(true);
sanitizer.parseUrl(authUrl);
return sanitizer.getValue(OsmOAuth.URL_PARAM_VERIFIER);
}
});
webview.loadUrl(authUrl);
}
protected void finishWebviewAuth(final String key, final String secret, final String verifier, final OsmOAuth.AuthType type)
{
ThreadPool.getWorker().execute(new Runnable() {
@Override
public void run()
{
final String[] auth = OsmOAuth.nativeAuthWithWebviewToken(key, secret, verifier);
UiThread.run(new Runnable() {
@Override
public void run()
{
processAuth(auth, type);
}
});
}
});
}
protected void recoverPassword()
{
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(Constants.Url.OSM_RECOVER_PASSWORD)));
}
protected void register()
{
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(Constants.Url.OSM_REGISTER)));
dismiss();
}
protected void processAuth(@Size(2) String[] auth, OsmOAuth.AuthType type)
{
if (auth == null)
{
if (isAdded())
{
new AlertDialog.Builder(getActivity()).setTitle(R.string.editor_login_error_dialog)
.setPositiveButton(android.R.string.ok, null).show();
Statistics.INSTANCE.trackEvent(Statistics.EventName.EDITOR_AUTH_REQUEST_RESULT,
Statistics.params().add(Statistics.EventParam.IS_SUCCESS, false).add(Statistics.EventParam.TYPE, type.name));
}
return;
}
OsmOAuth.setAuthorization(auth[0], auth[1]);
dismiss();
Statistics.INSTANCE.trackEvent(Statistics.EventName.EDITOR_AUTH_REQUEST_RESULT,
Statistics.params().add(Statistics.EventParam.IS_SUCCESS, true).add(Statistics.EventParam.TYPE, type.name));
mOsmAuthDelegate = new OsmAuthFragmentDelegate(this);
mOsmAuthDelegate.onViewCreated(view, savedInstanceState);
}
}

View file

@ -1,30 +1,21 @@
package com.mapswithme.maps.editor;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.net.Uri;
import android.net.UrlQuerySanitizer;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.Size;
import android.support.v7.app.AlertDialog;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import com.mapswithme.maps.R;
import com.mapswithme.maps.widget.InputWebView;
import com.mapswithme.maps.base.BaseMwmToolbarFragment;
import com.mapswithme.maps.widget.ToolbarController;
import com.mapswithme.util.Constants;
import com.mapswithme.util.concurrency.ThreadPool;
import com.mapswithme.util.concurrency.UiThread;
import com.mapswithme.util.statistics.Statistics;
public class AuthFragment extends BaseAuthFragment implements View.OnClickListener
public class AuthFragment extends BaseMwmToolbarFragment
{
private OsmAuthFragmentDelegate mOsmAuthDelegate;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)
@ -37,10 +28,8 @@ public class AuthFragment extends BaseAuthFragment implements View.OnClickListen
{
super.onViewCreated(view, savedInstanceState);
mToolbarController.setTitle(R.string.thank_you);
view.findViewById(R.id.login_osm).setOnClickListener(this);
view.findViewById(R.id.login_facebook).setOnClickListener(this);
view.findViewById(R.id.login_google).setOnClickListener(this);
view.findViewById(R.id.register).setOnClickListener(this);
mOsmAuthDelegate = new OsmAuthFragmentDelegate(this);
mOsmAuthDelegate.onViewCreated(view, savedInstanceState);
}
@Override
@ -56,136 +45,4 @@ public class AuthFragment extends BaseAuthFragment implements View.OnClickListen
}
};
}
@Override
public void onClick(View v)
{
// TODO show/hide spinners
switch (v.getId())
{
case R.id.login_osm:
Statistics.INSTANCE.trackAuthRequest(OsmOAuth.AuthType.OSM);
loginOsm();
break;
case R.id.login_facebook:
Statistics.INSTANCE.trackAuthRequest(OsmOAuth.AuthType.FACEBOOK);
loginWebview(OsmOAuth.AuthType.FACEBOOK);
break;
case R.id.login_google:
Statistics.INSTANCE.trackAuthRequest(OsmOAuth.AuthType.GOOGLE);
loginWebview(OsmOAuth.AuthType.GOOGLE);
break;
case R.id.lost_password:
Statistics.INSTANCE.trackEvent(Statistics.EventName.EDITOR_LOST_PASSWORD);
recoverPassword();
break;
case R.id.register:
Statistics.INSTANCE.trackEvent(Statistics.EventName.EDITOR_REG_REQUEST);
register();
break;
}
}
protected void loginOsm()
{
getMwmActivity().replaceFragment(OsmAuthFragment.class, null, null);
}
@SuppressLint("SetJavaScriptEnabled")
protected void loginWebview(final OsmOAuth.AuthType type)
{
final WebView webview = new InputWebView(getActivity());
webview.getSettings().setJavaScriptEnabled(true);
final AlertDialog dialog = new AlertDialog.Builder(getActivity()).setView(webview).create();
ThreadPool.getWorker().execute(new Runnable()
{
@Override
public void run()
{
final String[] auth = (type == OsmOAuth.AuthType.FACEBOOK) ? OsmOAuth.nativeGetFacebookAuthUrl()
: OsmOAuth.nativeGetGoogleAuthUrl();
UiThread.run(new Runnable()
{
@Override
public void run()
{
if (isAdded())
loadWebviewAuth(dialog, webview, auth, type);
}
});
}
});
dialog.show();
}
protected void loadWebviewAuth(final AlertDialog dialog, final WebView webview, @Size(3) final String[] auth, final OsmOAuth.AuthType type)
{
if (auth == null)
{
// TODO show some dialog
return;
}
final String authUrl = auth[0];
webview.setWebViewClient(new WebViewClient()
{
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
{
if (OsmOAuth.shouldReloadWebviewUrl(url))
{
webview.loadUrl(authUrl);
}
else if (url.contains(OsmOAuth.URL_PARAM_VERIFIER))
{
finishWebviewAuth(auth[1], auth[2], getVerifierFromUrl(url), type);
dialog.cancel();
return true;
}
return false;
}
private String getVerifierFromUrl(String authUrl)
{
UrlQuerySanitizer sanitizer = new UrlQuerySanitizer();
sanitizer.setAllowUnregisteredParamaters(true);
sanitizer.parseUrl(authUrl);
return sanitizer.getValue(OsmOAuth.URL_PARAM_VERIFIER);
}
});
webview.loadUrl(authUrl);
}
protected void finishWebviewAuth(final String key, final String secret, final String verifier, final OsmOAuth.AuthType type)
{
ThreadPool.getWorker().execute(new Runnable() {
@Override
public void run()
{
final String[] auth = OsmOAuth.nativeAuthWithWebviewToken(key, secret, verifier);
UiThread.run(new Runnable() {
@Override
public void run()
{
processAuth(auth, type);
}
});
}
});
}
protected void recoverPassword()
{
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(Constants.Url.OSM_RECOVER_PASSWORD)));
}
protected void register()
{
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(Constants.Url.OSM_REGISTER)));
}
}

View file

@ -1,33 +0,0 @@
package com.mapswithme.maps.editor;
import android.support.annotation.Size;
import android.support.v7.app.AlertDialog;
import com.mapswithme.maps.R;
import com.mapswithme.maps.base.BaseMwmToolbarFragment;
import com.mapswithme.util.Utils;
import com.mapswithme.util.statistics.Statistics;
public abstract class BaseAuthFragment extends BaseMwmToolbarFragment
{
protected void processAuth(@Size(2) String[] auth, OsmOAuth.AuthType type)
{
if (auth == null)
{
if (isAdded())
{
new AlertDialog.Builder(getActivity()).setTitle(R.string.editor_login_error_dialog)
.setPositiveButton(android.R.string.ok, null).show();
Statistics.INSTANCE.trackEvent(Statistics.EventName.EDITOR_AUTH_REQUEST_RESULT,
Statistics.params().add(Statistics.EventParam.IS_SUCCESS, false).add(Statistics.EventParam.TYPE, type.name));
}
return;
}
OsmOAuth.setAuthorization(auth[0], auth[1]);
Utils.navigateToParent(getActivity());
Statistics.INSTANCE.trackEvent(Statistics.EventName.EDITOR_AUTH_REQUEST_RESULT,
Statistics.params().add(Statistics.EventParam.IS_SUCCESS, true).add(Statistics.EventParam.TYPE, type.name));
}
}

View file

@ -16,6 +16,7 @@ import android.widget.TextView;
import com.mapswithme.maps.MwmApplication;
import com.mapswithme.maps.R;
import com.mapswithme.maps.base.BaseMwmToolbarFragment;
import com.mapswithme.maps.widget.ToolbarController;
import com.mapswithme.util.Constants;
import com.mapswithme.util.Graphics;
@ -24,8 +25,10 @@ import com.mapswithme.util.UiUtils;
import com.mapswithme.util.concurrency.ThreadPool;
import com.mapswithme.util.concurrency.UiThread;
public class OsmAuthFragment extends BaseAuthFragment implements View.OnClickListener
public class OsmAuthFragment extends BaseMwmToolbarFragment implements View.OnClickListener
{
private OsmAuthFragmentDelegate mDelegate;
private ProgressBar mProgress;
private TextView mTvLogin;
private View mTvLostPassword;
@ -61,6 +64,8 @@ public class OsmAuthFragment extends BaseAuthFragment implements View.OnClickLis
public void onViewCreated(View view, @Nullable Bundle savedInstanceState)
{
super.onViewCreated(view, savedInstanceState);
mDelegate = new OsmAuthFragmentDelegate(this);
mDelegate.onViewCreated(view, savedInstanceState);
mToolbarController.setTitle(R.string.login);
mEtLogin = (EditText) view.findViewById(R.id.osm_username);
mEtPassword = (EditText) view.findViewById(R.id.osm_password);
@ -108,7 +113,7 @@ public class OsmAuthFragment extends BaseAuthFragment implements View.OnClickLis
public void run()
{
final String[] auth = OsmOAuth.nativeAuthWithPassword(username, password);
final String username = auth == null ? null : OsmOAuth.nativeGetOsmUsername(auth[0], auth[1]);
UiThread.run(new Runnable()
{
@Override
@ -120,7 +125,7 @@ public class OsmAuthFragment extends BaseAuthFragment implements View.OnClickLis
enableInput(true);
UiUtils.hide(mProgress);
mTvLogin.setText(R.string.login);
processAuth(auth, OsmOAuth.AuthType.OSM);
mDelegate.processAuth(auth, OsmOAuth.AuthType.OSM, username);
}
});
}

View file

@ -0,0 +1,198 @@
package com.mapswithme.maps.editor;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.net.Uri;
import android.net.UrlQuerySanitizer;
import android.os.Bundle;
import android.support.annotation.IdRes;
import android.support.annotation.Nullable;
import android.support.annotation.Size;
import android.support.v4.app.Fragment;
import android.support.v7.app.AlertDialog;
import android.view.View;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import com.mapswithme.maps.R;
import com.mapswithme.maps.base.BaseMwmFragmentActivity;
import com.mapswithme.maps.widget.InputWebView;
import com.mapswithme.util.Constants;
import com.mapswithme.util.Utils;
import com.mapswithme.util.concurrency.ThreadPool;
import com.mapswithme.util.concurrency.UiThread;
import com.mapswithme.util.statistics.Statistics;
public class OsmAuthFragmentDelegate implements View.OnClickListener
{
private final Fragment mFragment;
public OsmAuthFragmentDelegate(Fragment fragment)
{
mFragment = fragment;
}
public void onViewCreated(View view, @Nullable Bundle savedInstanceState)
{
for (@IdRes int childId : new int[] {R.id.login_osm, R.id.login_facebook, R.id.login_google, R.id.register})
{
final View v = view.findViewById(childId);
if (v != null)
v.setOnClickListener(this);
}
}
@Override
public void onClick(View v)
{
// TODO show/hide spinners
switch (v.getId())
{
case R.id.login_osm:
Statistics.INSTANCE.trackAuthRequest(OsmOAuth.AuthType.OSM);
loginOsm();
break;
case R.id.login_facebook:
Statistics.INSTANCE.trackAuthRequest(OsmOAuth.AuthType.FACEBOOK);
loginWebview(OsmOAuth.AuthType.FACEBOOK);
break;
case R.id.login_google:
Statistics.INSTANCE.trackAuthRequest(OsmOAuth.AuthType.GOOGLE);
loginWebview(OsmOAuth.AuthType.GOOGLE);
break;
case R.id.lost_password:
Statistics.INSTANCE.trackEvent(Statistics.EventName.EDITOR_LOST_PASSWORD);
recoverPassword();
break;
case R.id.register:
Statistics.INSTANCE.trackEvent(Statistics.EventName.EDITOR_REG_REQUEST);
register();
break;
}
}
protected void processAuth(@Size(2) String[] auth, OsmOAuth.AuthType type, String username)
{
if (auth == null)
{
if (mFragment.isAdded())
{
new AlertDialog.Builder(mFragment.getActivity()).setTitle(R.string.editor_login_error_dialog)
.setPositiveButton(android.R.string.ok, null).show();
Statistics.INSTANCE.trackEvent(Statistics.EventName.EDITOR_AUTH_REQUEST_RESULT,
Statistics.params().add(Statistics.EventParam.IS_SUCCESS, false).add(Statistics.EventParam.TYPE, type.name));
}
return;
}
OsmOAuth.setAuthorization(auth[0], auth[1], username);
Utils.navigateToParent(mFragment.getActivity());
Statistics.INSTANCE.trackEvent(Statistics.EventName.EDITOR_AUTH_REQUEST_RESULT,
Statistics.params().add(Statistics.EventParam.IS_SUCCESS, true).add(Statistics.EventParam.TYPE, type.name));
}
protected void loginOsm()
{
((BaseMwmFragmentActivity) mFragment.getActivity()).replaceFragment(OsmAuthFragment.class, null, null);
}
@SuppressLint("SetJavaScriptEnabled")
protected void loginWebview(final OsmOAuth.AuthType type)
{
final WebView webview = new InputWebView(mFragment.getActivity());
webview.getSettings().setJavaScriptEnabled(true);
final AlertDialog dialog = new AlertDialog.Builder(mFragment.getActivity()).setView(webview).create();
ThreadPool.getWorker().execute(new Runnable()
{
@Override
public void run()
{
final String[] auth = (type == OsmOAuth.AuthType.FACEBOOK) ? OsmOAuth.nativeGetFacebookAuthUrl()
: OsmOAuth.nativeGetGoogleAuthUrl();
UiThread.run(new Runnable()
{
@Override
public void run()
{
if (mFragment.isAdded())
loadWebviewAuth(dialog, webview, auth, type);
}
});
}
});
dialog.show();
}
protected void loadWebviewAuth(final AlertDialog dialog, final WebView webview, @Size(3) final String[] auth, final OsmOAuth.AuthType type)
{
if (auth == null)
{
// TODO show some dialog
return;
}
final String authUrl = auth[0];
webview.setWebViewClient(new WebViewClient()
{
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
{
if (OsmOAuth.shouldReloadWebviewUrl(url))
{
webview.loadUrl(authUrl);
}
else if (url.contains(OsmOAuth.URL_PARAM_VERIFIER))
{
finishWebviewAuth(auth[1], auth[2], getVerifierFromUrl(url), type);
dialog.cancel();
return true;
}
return false;
}
private String getVerifierFromUrl(String authUrl)
{
UrlQuerySanitizer sanitizer = new UrlQuerySanitizer();
sanitizer.setAllowUnregisteredParamaters(true);
sanitizer.parseUrl(authUrl);
return sanitizer.getValue(OsmOAuth.URL_PARAM_VERIFIER);
}
});
webview.loadUrl(authUrl);
}
protected void finishWebviewAuth(final String key, final String secret, final String verifier, final OsmOAuth.AuthType type)
{
ThreadPool.getWorker().execute(new Runnable() {
@Override
public void run()
{
final String[] auth = OsmOAuth.nativeAuthWithWebviewToken(key, secret, verifier);
final String username = auth == null ? null : OsmOAuth.nativeGetOsmUsername(auth[0], auth[1]);
UiThread.run(new Runnable() {
@Override
public void run()
{
processAuth(auth, type, username);
}
});
}
});
}
protected void recoverPassword()
{
mFragment.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(Constants.Url.OSM_RECOVER_PASSWORD)));
}
protected void register()
{
mFragment.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(Constants.Url.OSM_REGISTER)));
}
}

View file

@ -42,6 +42,7 @@ public final class OsmOAuth
private static final String PREF_OSM_TOKEN = "OsmToken";
private static final String PREF_OSM_SECRET = "OsmSecret";
private static final String PREF_OSM_USERNAME = "OsmUsername";
public static final String URL_PARAM_VERIFIER = "oauth_verifier";
@ -61,11 +62,17 @@ public final class OsmOAuth
return MwmApplication.prefs().getString(PREF_OSM_SECRET, "");
}
public static void setAuthorization(String token, String secret)
public static String getUsername()
{
return MwmApplication.prefs().getString(PREF_OSM_USERNAME, "");
}
public static void setAuthorization(String token, String secret, String username)
{
MwmApplication.prefs().edit()
.putString(PREF_OSM_TOKEN, token)
.putString(PREF_OSM_SECRET, secret)
.putString(PREF_OSM_USERNAME, username)
.apply();
}
@ -74,6 +81,7 @@ public final class OsmOAuth
MwmApplication.prefs().edit()
.remove(PREF_OSM_TOKEN)
.remove(PREF_OSM_SECRET)
.remove(PREF_OSM_USERNAME)
.apply();
}
@ -100,7 +108,7 @@ public final class OsmOAuth
@WorkerThread
@Size(2)
@Nullable
public static native String[] nativeAuthWithWebviewToken(String secret, String token, String verifier);
public static native String[] nativeAuthWithWebviewToken(String key, String secret, String verifier);
/**
* @return url for web auth, and token with secret for finishing authorization later
@ -115,4 +123,8 @@ public final class OsmOAuth
@Size(3)
@Nullable
public static native String[] nativeGetGoogleAuthUrl();
@WorkerThread
@Nullable
public static native String nativeGetOsmUsername(String token, String secret);
}

View file

@ -17,7 +17,6 @@ import com.mapswithme.util.UiUtils;
public class ProfileFragment extends AuthFragment implements View.OnClickListener
{
private View mEditsBlock;
private TextView mEditsLocal;
private View mEditsMore;
private TextView mEditsSent;
@ -38,15 +37,15 @@ public class ProfileFragment extends AuthFragment implements View.OnClickListene
{
mLogout = mToolbarController.findViewById(R.id.logout);
mLogout.setOnClickListener(this);
mEditsBlock = view.findViewById(R.id.block_edits);
UiUtils.show(mEditsBlock);
final View localEdits = mEditsBlock.findViewById(R.id.local_edits);
View editsBlock = view.findViewById(R.id.block_edits);
UiUtils.show(editsBlock);
final View localEdits = editsBlock.findViewById(R.id.local_edits);
((ImageView) localEdits.findViewById(R.id.image)).setImageResource(R.drawable.ic_device);
mEditsLocal = (TextView) localEdits.findViewById(R.id.title);
mEditsMore = localEdits.findViewById(R.id.more);
mEditsMore.setOnClickListener(this);
UiUtils.hide(localEdits.findViewById(R.id.subtitle), localEdits.findViewById(R.id.more));
final View sentEdits = mEditsBlock.findViewById(R.id.sent_edits);
final View sentEdits = editsBlock.findViewById(R.id.sent_edits);
((ImageView) sentEdits.findViewById(R.id.image)).setImageResource(R.drawable.ic_upload);
mEditsSent = (TextView) sentEdits.findViewById(R.id.title);
mEditsSentDate = (TextView) sentEdits.findViewById(R.id.subtitle);
@ -101,8 +100,6 @@ public class ProfileFragment extends AuthFragment implements View.OnClickListene
}
}).tint().show();
break;
default:
super.onClick(v);
}
}
}

View file

@ -25,6 +25,7 @@ import com.mapswithme.maps.R;
import com.mapswithme.maps.base.BaseActivity;
import com.mapswithme.maps.base.BaseActivityDelegate;
import com.mapswithme.maps.base.OnBackPressListener;
import com.mapswithme.maps.editor.OsmOAuth;
import com.mapswithme.maps.editor.ProfileActivity;
import com.mapswithme.util.FragmentListHelper;
import com.mapswithme.util.ThemeUtils;
@ -80,7 +81,15 @@ public class SettingsActivity extends PreferenceActivity
mHeaders.clear();
for (Header h : target)
{
mHeaders.put(h.id, h);
// Hack to change profile header to username, if user is logged in.
if (h.id == R.id.osm_profile && OsmOAuth.isAuthorized())
{
h.titleRes = 0;
h.title = OsmOAuth.getUsername();
}
}
}
@Override