Nastał ten piękny moment kiedy kilka modułów aplikacji zostało sklejonych i pojawiają się coraz większe zalążki całej aplikacji. W tym poście przedstawię proces dodawania i modyfikowania poprzedniego stworzonego kodu, efektem działań jest logowanie do aplikacji za pomocą aplikacji i możliwość wyświetlenia swojego profilu.
Klasa FacebookLogin
Klasa została prawie cała przebudowana. Dodane zostały funkcjonalności pozwalające zapisać nowego użytkownika do bazy oraz zapisanie zalogowanego użytkownika do klasy SaveSharedPreference, o której za chwilę. Poniżej umieszczam aktualny kod klasy FacebookLogin, trzeba przyznać, że trochę się rozrosła w porównaniu do pierwszej wersji.
public class FacebookLogin extends Fragment { private CallbackManager callbackManager; private LoginButton loginButton; private boolean postingEnabled = false; private ProfileTracker profileTracker; private TextView greeting; private String url; private String emailCheckStatus; private FacebookLogin instance; private String lastLocalization; private String addingNewUser; private int userId; private AccessTokenTracker fbTracker; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); instance = this; FacebookSdk.sdkInitialize(getActivity()); } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); callbackManager.onActivityResult(requestCode, resultCode, data); } @Nullable @Override public View onCreateView(final LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.facebook_login, parent, false); greeting = (TextView) v.findViewById(R.id.greeting); loginButton = (LoginButton) v.findViewById(R.id.login_button); loginButton.setFragment(this); loginButton.setReadPermissions(Arrays.asList( "public_profile", "email", "user_birthday", "user_location")); callbackManager = CallbackManager.Factory.create(); loginButton.registerCallback(callbackManager, new FacebookCallback<LoginResult>() { @Override public void onSuccess(LoginResult loginResult) { Toast toast = Toast.makeText(getActivity(), "Logged In", Toast.LENGTH_SHORT); postingEnabled = true; GraphRequest request = GraphRequest.newMeRequest(AccessToken.getCurrentAccessToken(), new GraphRequest.GraphJSONObjectCallback() { @Override public void onCompleted(JSONObject object, GraphResponse response) { try { String first_name = object.getString("first_name"); String last_name = object.getString("last_name"); String email = object.getString("email"); String birthdaySource = object.getString("birthday"); String[] date = birthdaySource.split("/"); String birthday = date[2] + ", " + date[1] + ", " + date[0]; String city = object.getJSONObject("location").getString("name"); url = "http://chinet.cba.pl/meethere.php?thatEmail=" + email; try { emailCheckStatus = new dbOperation(instance).execute().get(); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } if (Objects.equals(emailCheckStatus, "success")) { LocationTracker locationTracker = LocationTracker.getInstance(); if (locationTracker.canGetLocation()) { lastLocalization = locationTracker.getLatitude() + ", " + locationTracker.getLongitude(); } locationTracker.stopUsingGPS(); url = "http://chinet.cba.pl/meethere.php?addUser=" + first_name + "&surname=" + last_name + "&email=" + email + "&city=" + city + "&dayOfBirthday=" + birthday + "&lastLocalization=" + lastLocalization; try { addingNewUser = new dbOperation(instance).execute().get(); userId = Integer.parseInt(addingNewUser); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } else { Log.d("Email check", "fail"); userId = Integer.parseInt(emailCheckStatus); } SaveSharedPreference.setPrefId(getContext(), userId); Log.d("UserFacebookData", email + birthday + city); } catch (JSONException e) { e.printStackTrace(); } } }); Bundle parameters = new Bundle(); parameters.putString("fields", "id,first_name,last_name,birthday,location,link,email"); request.setParameters(parameters); request.executeAsync(); loginButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { LoginManager.getInstance().logInWithReadPermissions(getActivity(), Arrays.asList("public_profile")); if(!postingEnabled) { postingEnabled = true; }else{ postingEnabled = false; } } }); toast.show(); updateUI(); } @Override public void onCancel() { updateUI(); } @Override public void onError(FacebookException exception) { updateUI(); } }); fbTracker = new AccessTokenTracker() { @Override protected void onCurrentAccessTokenChanged(AccessToken accessToken, AccessToken accessToken2) { if (accessToken2 == null) { Log.d("FB", "User Logged Out."); SharedPreferences.Editor editor = getSharedPreferences(getContext()).edit(); editor.clear(); editor.commit(); } } }; profileTracker = new ProfileTracker() { @Override protected void onCurrentProfileChanged(Profile oldProfile, Profile currentProfile) { updateUI(); } }; return v; } @Override public void onResume() { super.onResume(); // Call the 'activateApp' method to log an app event for use in analytics and advertising // reporting. Do so in the onResume methods of the primary Activities that an app may be // launched into. AppEventsLogger.activateApp(getActivity()); updateUI(); } @Override public void onPause() { super.onPause(); // Call the 'deactivateApp' method to log an app event for use in analytics and advertising // reporting. Do so in the onPause methods of the primary Activities that an app may be // launched into. AppEventsLogger.deactivateApp(getActivity()); } @Override public void onDestroy() { super.onDestroy(); profileTracker.stopTracking(); } private void updateUI() { boolean enableButtons = AccessToken.getCurrentAccessToken() != null; Profile profile = Profile.getCurrentProfile(); if (enableButtons && profile != null) { greeting.setText(getString(R.string.hello_user, profile.getFirstName())); } else { greeting.setText(null); } } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); } private class dbOperation extends AsyncTask<String, Void, String> { private static final String TAG = "dbOperation"; private FacebookLogin facebookLogin; public dbOperation(FacebookLogin facebookLogin) { this.facebookLogin = facebookLogin; } @Override protected String doInBackground(String... strings) { WebServiceHandler webServiceHandler = new WebServiceHandler(); String jsonStr = webServiceHandler.makeServiceCall(url); Log.d(TAG, "Response form url: " + jsonStr); if (jsonStr != null) { try { JSONObject jsonObject = new JSONObject(jsonStr); String response = jsonObject.getString("operation"); String id = jsonObject.getString("id"); if (Objects.equals(response, "success")) { return "success"; } else { return id; } } catch (JSONException e) { e.printStackTrace(); } } return "fail"; } } }
Z racji, że klasa FacebookLogin dziedziczy teraz po klasie Fragment, potrzebne jest jej wywołanie w LoginActivity:
FragmentManager fm = getSupportFragmentManager(); Fragment fragment = fm.findFragmentById(R.id.fragment_container); if (fragment == null) { fragment = new FacebookLogin(); fm.beginTransaction() .add(R.id.fragment_container, fragment) .commit(); }
Plik z layoutem FacebookLogin wygląda następująco:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:facebook="http://schemas.android.com/apk/res-auto" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/greeting" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_gravity="center" android:textColor="#333" android:textSize="18sp"/> <com.facebook.login.widget.LoginButton android:id="@+id/login_button" android:layout_width="250dp" android:layout_height="wrap_content" android:layout_marginTop="5dp" android:layout_gravity="center_horizontal" facebook:com_facebook_confirm_logout="true" facebook:com_facebook_tooltip_mode="never_display" /> </LinearLayout>
Przechowywanie zalogowanego użytkownika w pamięci
Zanim przejdziemy do klasy odpowiedzialnej za całą magię, wypadałoby wspomnieć o modyfikacjach jakich dokonałem w klasie UserActivity. Klasa pobiera ID użytkownika z klasy SaveSharedPreference i sprawdza czy to ID nie jest równe 0. Jeśli tak oznacza to, że użytkownik nie jest zalogowany i jest przekierowywany do aktywności logowania, w przeciwnym wypadku kod klasy wykonywany jest normalnie.
userId = SaveSharedPreference.getId(getApplicationContext()); if (userId == 0) { Intent intent = new Intent(this, LoginActivity.class); startActivity(intent); } else { //UserActivity code }
Nadszedł czas na klasę SaveSharedPreference jej zadaniem jest przechowywanie numeru ID zalogowanego użytkownika. Jeśli ktoś będzie chciał pobrać ID, kiedy nikt nie jest zalogowany zostanie mu zwrócone 0 oznaczające brak takiego użytkownika.
public class SaveSharedPreference { static final String PREF_ID = "ID"; static SharedPreferences getSharedPreferences(Context context) { return PreferenceManager.getDefaultSharedPreferences(context); } public static void setPrefId(Context context, int id) { Editor editor = getSharedPreferences(context).edit(); editor.putInt(PREF_ID, id); editor.commit(); } public static int getId(Context context) { if (getSharedPreferences(context).contains(PREF_ID)) { return getSharedPreferences(context).getInt(PREF_ID, ' '); } else { return 0; } } }
Przede mną jeszcze dużo pracy nad aplikacją, ale pierwsze widoczne, działające zalążki gotowej aplikacji tylko motywują do dalszej pracy.
Fajna sprawa!
Jak będziesz miał chwilę to postaraj się trochę „uszczuplić” metodę onCreateView – z tego co widzę ma ok.130 linii – warto ją rozbić na kilka ‚podmetod’. Żeby powrót do kodu po większej przerwie nie był kłopotem 🙂
Dobra robota! 🙂
PolubieniePolubienie
Dzięki! Zajmę się tym w wolnej chwili, bo faktyczne jest ona trochę przytłaczająca.
PolubieniePolubienie