java - Android sign in button in a fragment -
i'm trying have google sign in button android application.
i googled , found quickstart tutorials , them created following code.
in androidmanifest.xml add following:
<meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />
my fragment xml (fragment_main_menu.xml):
<relativelayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingleft="@dimen/activity_horizontal_margin" android:paddingright="@dimen/activity_horizontal_margin" android:paddingtop="@dimen/activity_vertical_margin" android:paddingbottom="@dimen/activity_vertical_margin" tools:context="com.tuxin.myalcoholist.myalcoholist.myalcoholist.mainmenuactivity$placeholderfragment"> <button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/add_drink" android:id="@+id/add_drink" android:layout_alignparenttop="true" android:layout_centerhorizontal="true" android:layout_margintop="36dp" android:onclick="addstringclickhandler" /> <com.google.android.gms.common.signinbutton android:id="@+id/sign_in_button" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </relativelayout>
my main menu activity contains following code:
package com.tuxin.myalcoholist.myalcoholist.myalcoholist; import android.app.pendingintent; import android.content.intentsender; import android.support.v7.app.actionbaractivity; import android.support.v7.app.actionbar; import android.support.v4.app.fragment; import android.os.bundle; import android.util.log; import android.view.layoutinflater; import android.view.menu; import android.view.menuitem; import android.view.view; import android.view.viewgroup; import android.os.build; import android.widget.toast; import com.google.android.gms.common.connectionresult; import com.google.android.gms.common.signinbutton; import com.google.android.gms.common.api.googleapiclient; import com.google.android.gms.plus.plus; import com.google.android.gms.plus.model.people.person; public class mainmenuactivity extends actionbaractivity { @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main_menu); if (savedinstancestate == null) { getsupportfragmentmanager().begintransaction() .add(r.id.container, new placeholderfragment()) .commit(); } } @override public boolean oncreateoptionsmenu(menu menu) { // inflate menu; adds items action bar if present. getmenuinflater().inflate(r.menu.main_menu, menu); return true; } @override public boolean onoptionsitemselected(menuitem item) { // handle action bar item clicks here. action bar // automatically handle clicks on home/up button, long // specify parent activity in androidmanifest.xml. int id = item.getitemid(); if (id == r.id.action_settings) { return true; } return super.onoptionsitemselected(item); } public void addcocktailclickhandler(view v) { } /** * placeholder fragment containing simple view. */ public class placeholderfragment extends fragment implements view.onclicklistener, googleapiclient.connectioncallbacks, googleapiclient.onconnectionfailedlistener { private signinbutton msigninbutton; private googleapiclient mgoogleapiclient; private int msigninprogress; private pendingintent msigninintent; private int msigninerror; private static final int state_default = 0; private static final int state_sign_in = 1; private static final int state_in_progress = 2; private static final int rc_sign_in = 0; private static final string saved_progress = "sign_in_progress"; public placeholderfragment() { } @override public view oncreateview(layoutinflater inflater, viewgroup container, bundle savedinstancestate) { view rootview = inflater.inflate(r.layout.fragment_main_menu, container, false); msigninbutton = (signinbutton) rootview.findviewbyid(r.id.sign_in_button); msigninbutton.setonclicklistener(this); mgoogleapiclient = buildgoogleapiclient(); return rootview; } @override public void onstart() { super.onstart(); mgoogleapiclient.connect();; } @override public void onstop() { super.onstop(); if (mgoogleapiclient.isconnected()) { mgoogleapiclient.disconnect();; } } @override public void onsaveinstancestate(bundle outstate) { super.onsaveinstancestate(outstate); outstate.putint(saved_progress, msigninprogress); } @override public void onclick(view v) { if (!mgoogleapiclient.isconnecting()) { // process button clicks when googleapiclient not transitioning // between connected , not connected. switch (v.getid()) { case r.id.sign_in_button: toast.maketext(getactivity().getapplicationcontext(),"connecting",toast.length_long).show(); resolvesigninerror(); break; } } } private googleapiclient buildgoogleapiclient() { // when build googleapiclient specify connected , // connection failed callbacks should returned, google apis our // app uses , oauth 2.0 scopes our app requests. return new googleapiclient.builder(getactivity().getapplicationcontext()) .addconnectioncallbacks(this) .addonconnectionfailedlistener(this) .addapi(plus.api, null) .addscope(plus.scope_plus_login) .build(); } private void resolvesigninerror() { if (msigninintent != null) { // have intent allow our user sign in or // resolve error. example if user needs // select account sign in with, or if need consent // permissions app requesting. try { // send pending intent stored on recent // onconnectionfailed callback. allow user // resolve error preventing our connection // google play services. msigninprogress = state_in_progress; startintentsenderforresult(msigninintent.getintentsender(), rc_sign_in, null, 0, 0, 0); } catch (intentsender.sendintentexception e) { toast.maketext(getapplicationcontext(),"sign in intent not sent: " + e.getlocalizedmessage(),toast.length_long).show(); // intent canceled before sent. attempt connect // updated connectionresult. msigninprogress = state_sign_in; mgoogleapiclient.connect(); } } else { // google play services wasn't able provide intent // error types, show default google play services error // dialog may still start intent on our behalf if // user can resolve issue. toast.maketext(getapplicationcontext(),"play services error",toast.length_long).show(); } } @override public void onconnected(bundle bundle) { // retrieve profile information personalize our app user. person currentuser = plus.peopleapi.getcurrentperson(mgoogleapiclient); toast.maketext(getapplicationcontext(),currentuser.getdisplayname(),toast.length_long).show(); msigninprogress = state_default; } @override public void onconnectionsuspended(int i) { } @override public void onconnectionfailed(connectionresult connectionresult) { toast.maketext(getapplicationcontext(),"onconnectionfailed: connectionresult.geterrorcode() = " + connectionresult.geterrorcode(),toast.length_long).show(); if (msigninprogress != state_in_progress) { // not have intent in progress should store latest // error resolution intent use when sign in button clicked. msigninintent = connectionresult.getresolution(); msigninerror = connectionresult.geterrorcode(); if (msigninprogress == state_sign_in) { // state_sign_in indicates user clicked sign in button // should continue processing errors until user signed in // or click cancel. resolvesigninerror(); } } // in sample consider user signed out whenever not have // connection google play services. onsignedout(); } private void onsignedout() { toast.maketext(getapplicationcontext(),"signed out",toast.length_long).show(); } } }
i understood must have arm emulator of version 4.4.2 in order play services work in emulator, did that.. , when click on google sign in button toasts message "connecting" , after "play services error"
so doing wrong? missing ?
any information regarding issue appreciated.
update
now i'm using google api x86 image. allowed me choose user login with, , failed error code 4 , "an internal error occured" toast message
do need sign application first? still didn't quite understand how google play knows relate application registered @ console.developers.google.com. didn't use certificate or anything..
any ideas?
another update
i created new client id based on quickstart tutorial, typed package com.tuxin.myalcoholist , copyed sha1 string keytool command (using ~/.android/debug.keystore
keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore -list -v
i still same results.
i believe have not installed google apis platform on emulator. reason getting error indicates service not available.
from docs:
install compatible version of google apis platform. if want test app on emulator, expand directory android 4.2.2 (api 17) or higher version, select google apis, , install it. create new avd google apis platform target.
update 1: regarding "an internal error occured" toast message, can occur when have copied wrong key value keytool. please follow quick start documentation, step 5.
the package name , sha1 of package, allows google link between app , client id generated in console. same information presented while creating client id, can see in image.
api requests sent directly google clients' android devices. google verifies each request originates android application matches package name , sha1 signing certificate fingerprint name listed below.
update 2: after installing google play services, did create new avd google apis target? if not please it, shown in below image. can check whether google play services available using isgoogleplayservicesavailable.
Comments
Post a Comment