Omówimy logowanie z użyciem konta FB oraz umieszczanie postów
https://tvoss.github.io/app-dev/wavelength/2017/05/07/facebook-login-with-xamarin.html
0. Utwórz konto deweloperskie FB i pobierz Facebook App ID
zob. opis i linki w https://developers.facebook.com/docs/accountkit/android#download-facebook-sdk
zob. też: https://developers.facebook.com/docs/facebook-login/android <--- otworzyć tę stronę
Wygodne w przypadku zwykłego Androida z Javą, bo ma skrypty, które generują kody z odpowiednimi numerami App ID
1. Tworzymy nowy projekt o nazwie FacebookDemo (Blank App, domyślne ustawienia)
2. Otwieramy Tools, NuGet Package Manager, Package Manager Console:
Install-Package Xamarin.Facebook
To samo można uzyskać przez Manage NuGet Packages w Solution Explorer. U mnie wersja 4.4.0.2
Są problemy. !!!!!!!!!!!!!!!!!!!!!!
Uwaga!
Poniższy opis (początek) według: https://developers.facebook.com/docs/facebook-login/android <--- otworzyć tę stronę
Rejestracja: https://developers.facebook.com/quickstarts/?platform=android
Po zatwierdzeniu należy kliknąć "Create App ID".
Należy podać nazwę (ja użyłem "PUM") i adres e-mail
Przydzielony zostanie wielocyfrowy numer (np. 1766900306675987) i pojawi się strona, która pokazuje wszystkie API, których możemy użyć.
1. Tworzymy nowy projekt o nazwie FacebookDemo (Blank App, domyślne ustawienia)
2. Przechodzimy do Gradle Scripts, build.gradle (Module: app)
apply plugin: 'com.android.application'
android {
compileSdkVersion 25
buildToolsVersion "25.0.3"
defaultConfig {
applicationId "pl.umk.fizyka.facebookdemo"
minSdkVersion 15
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
//dodane !!!!!!!!!!!!!!!!!!!!
repositories {
mavenCentral()
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:25.3.1'
compile 'com.android.support.constraint:constraint-layout:1.0.2'
compile 'com.facebook.android:facebook-android-sdk:[4,5)' //dodane !!!!!!!!!!!!!!!!!!!!
testCompile 'junit:junit:4.12'
}
3. Kompilujemy projekt (Ctrl+F9)
4. W pliku MainActivity.java dodajemy:
import com.facebook.FacebookSdk;
import com.facebook.appevents.AppEventsLogger;
Nie powinno być nic zaznaczonego na czerwono w tych liniach
LOGOWANIE
---------
5. Przechodzimy do res/values/strings.xml i dodajemy:
1766900306675987
fb1766900306675987
Zaloguj używając konta FB
Wyloguj
6. W pliku manifestu dodajemy (poza elementem application):
7. Do manifestu dodajemy też *******
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
8. Pobieramy OpenSSL: http://gnuwin32.sourceforge.net/packages/openssl.htm
Pobrałem pakiet w 'zip'-ie i rozpakowałem do c:\EXE\OpenSSL
9. Tworzenie klucza (bezpieczeństwo autoryzacji)
W katalogu c:\Program Files\Android\Android Studio\jre\bin\ uruchom 'cmd'
set PATH=%PATH%;C:\EXE\OpenSSL\bin
path
keytool -exportcert -alias androiddebugkey -keystore %HOMEPATH%\.android\debug.keystore | openssl sha1 -binary | openssl base64
Należy wprowadzić hasło ('haslo')
Otrzymamy 28-znakowy hash do developerki: Cmce+9aHdOoVtE7fS3B07tfj7Bc=
Hash do release (zob. https://developers.facebook.com/docs/facebook-login/android) - wymagany przy wrzucaniu do Google Play
10. Jeżeli chcemu "Single Sign On" z aplikacji, musimy ustawić na stronie i zapisać.
11. Dodajemy przycisk logowania przez FB do activity_main.xml:
12. Deklarujemy pola w klasie MainActivity:
TextView textView;
CallbackManager callbackManager;
13. W metodzie MainActivity.onCreate rejestrujemy funkcję zwrotną, która powiadamia o wynikach logowania
package pl.umk.fizyka.facebookdemo;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.view.ActionMode;
import android.widget.TextView;
import com.facebook.AccessToken;
import com.facebook.AccessTokenTracker;
import com.facebook.CallbackManager;
import com.facebook.FacebookCallback;
import com.facebook.FacebookException;
import com.facebook.login.LoginBehavior;
import com.facebook.login.LoginManager;
import com.facebook.login.LoginResult;
import com.facebook.login.widget.LoginButton;
import org.w3c.dom.Text;
public class MainActivity extends AppCompatActivity {
TextView textView;
CallbackManager callbackManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView)findViewById(R.id.hello);
textView.setText("Niezalogowany");
callbackManager = CallbackManager.Factory.create();
LoginButton loginButton = (LoginButton)findViewById(R.id.login_button);
loginButton.registerCallback(callbackManager, new FacebookCallback()
{
@Override
public void onSuccess(LoginResult loginResult)
{
AccessToken accessToken = loginResult.getAccessToken();
String s = "Zalogowany";
s += "\nAplikacja: " + accessToken.getApplicationId();
s += "\nUżytkownik: " + accessToken.getUserId();
//s += "\nToken: " + accessToken.getToken();
s += "\nTermin ważności: " + accessToken.getExpires().toString();
textView.setText(s);
}
@Override
public void onCancel()
{
textView.setText("Logowanie anulowane");
}
@Override
public void onError(FacebookException error)
{
textView.setText("Błąd logowania: " + error.getLocalizedMessage());
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
callbackManager.onActivityResult(requestCode, resultCode, data);
}
}
14. Przetestować (potrzebny dostęp do internetu z emulatora lub urządzenia)
15. Śledzenie zmian (w tym wylogoywanie i utrata ważności):
Kod dodany w onCreate:
//wylogowywanie i inne zmiany
AccessTokenTracker accessTokenTracker = new AccessTokenTracker()
{
@Override
protected void onCurrentAccessTokenChanged(AccessToken oldAccessToken, AccessToken currentAccessToken)
{
if(currentAccessToken == null)
textView.setText("Wylogowano");
}
};
Uwaga! W innych metodach zawsze można użyć
AccessToken accessToken = AccessToken.getCurrentAccessToken();
aby odczytać token.
16. Porządki na koniec.
Definiujemy metodę
private String getTokenInfo(AccessToken accessToken)
{
String s;
if(accessToken == null)
{
s = "Niezalogowany";
}
else
{
s = "Zalogowany";
s += "\nAplikacja: " + accessToken.getApplicationId();
s += "\nUżytkownik: " + accessToken.getUserId();
//s += "\nToken: " + accessToken.getToken();
s += "\nTermin ważności: " + accessToken.getExpires().toString();
}
return s;
}
Używamy jej w onCreate:
textView = (TextView)findViewById(R.id.hello);
//textView.setText("Niezalogowany");
AccessToken accessToken = AccessToken.getCurrentAccessToken();
textView.setText(getTokenInfo(accessToken));
Używamy jej w onSuccess:
public void onSuccess(LoginResult loginResult)
{
AccessToken accessToken = loginResult.getAccessToken();
textView.setText(getTokenInfo(accessToken));
}
i przy śledzeniu zmian:
AccessTokenTracker accessTokenTracker = new AccessTokenTracker()
{
@Override
protected void onCurrentAccessTokenChanged(AccessToken oldAccessToken, AccessToken currentAccessToken)
{
getTokenInfo(currentAccessToken);
}
};
UDOSTĘPNIANIE
-------------
Chodzi o umieszczanie wiadomości na samym FB, do messangera jest osobne API.
Uwaga! Zgodnie z polityką FB nie można w kontrolkach wstawiać żadnych domyślnych tekstów.
Opis: https://developers.facebook.com/docs/sharing/android
1. Do manifestu (w obrębie elementu application) dodaj
Numer to App ID.
2. Do interfejsu (plik activity_main.xml) dodajemy okno edycyjne i przycisk:
3. Bezpośrednie udostępnianie (przez mechanizm udostępniania - bez Facebook SDK):
final EditText treśćWpisu = (EditText)findViewById(R.id.treśćWpisu);
Button wyślijWpis = (Button)findViewById(R.id.wyślijWpis);
wyślijWpis.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
//wysyłanie poprzez dialog "Udostępnij" (bez Facebook SDK)
//wymaga instalacji aplikacji Facebook
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TEXT, treśćWpisu.getText());
//startActivity(Intent.createChooser(intent, "Udostępnij"));
}
});
4. Udostępnianie linku przez Facebook SDK:
final EditText treśćWpisu = (EditText)findViewById(R.id.treśćWpisu);
Button wyślijWpis = (Button)findViewById(R.id.wyślijWpis);
wyślijWpis.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
//link
ShareLinkContent zawartośćLink = new ShareLinkContent.Builder()
//.setContentDescription("Opis (wycofane)")
//.setContentTitle("Tytuł (wycofane)")
.setContentUrl(Uri.parse("http://www.fizyka.umk.pl/~jacek/dydaktyka"))
.setQuote(treśćWpisu.getText().toString())
.setShareHashtag(new ShareHashtag.Builder().setHashtag("#UMK").build())
.build();
try
{
ShareDialog shareDialog = new ShareDialog(MainActivity.this);
shareDialog.show(zawartośćLink);
//można pominąć drugi argument wybierający rodzaj okna dialogowego (domyślny ShareDialog.Mode.AUTOMATIC)
}
catch(Exception exc)
{
Toast.makeText(getApplicationContext(), "Błąd: " + exc.getLocalizedMessage(), Toast.LENGTH_LONG).show();
}
}
});
Poprawność linku i wydobywanych z niego informacji można sprawdzić na stronie:
https://developers.facebook.com/tools/debug/
5. Rejestrowanie się do informacji zwrotnej o udostępnieniu:
final EditText treśćWpisu = (EditText)findViewById(R.id.treśćWpisu);
Button wyślijWpis = (Button)findViewById(R.id.wyślijWpis);
wyślijWpis.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
//link
ShareLinkContent zawartośćLink = new ShareLinkContent.Builder()
//.setContentDescription("Opis (wycofane)")
//.setContentTitle("Tytuł (wycofane)")
.setContentUrl(Uri.parse("http://www.fizyka.umk.pl/~jacek/dydaktyka"))
.setQuote(treśćWpisu.getText().toString())
.setShareHashtag(new ShareHashtag.Builder().setHashtag("#UMK").build())
.build();
try
{
ShareDialog shareDialog = new ShareDialog(MainActivity.this);
FacebookCallback resultFacebookCallback = new FacebookCallback()
{
@Override
public void onSuccess(Sharer.Result result)
{
textView.setText("Wysłanie posta udało się");
}
@Override
public void onCancel()
{
textView.setText("Wysłanie posta zostało anulowane");
}
@Override
public void onError(FacebookException error)
{
textView.setText("Wysłanie posta nie powiodło się: " + error.getLocalizedMessage());
}
};
shareDialog.registerCallback(callbackManager, resultFacebookCallback);
shareDialog.show(zawartośćLink);
}
catch(Exception exc)
{
Toast.makeText(getApplicationContext(), "Błąd: " + exc.getLocalizedMessage(), Toast.LENGTH_LONG).show();
}
}
});
6. Publikowanie zdjęć
Uwaga! Wymaga dodatkowych uprawnień publikowania: publish_actions - bez tego będzie od razu nie udane publikowanie
Przed logowaniem:
LoginManager.getInstance().logInWithPublishPermissions(
this,
Arrays.asList("publish_actions"));
Uwaga! Przy pierwszym logowaniu pojawi się okno z prośba o potwierdzenie uprawnienia.
Uzupełnianie informacji o uprawnieniach:
private String getTokenInfo(AccessToken accessToken)
{
String s;
if(accessToken == null)
{
s = "Niezalogowany";
}
else
{
s = "Zalogowany";
s += "\nAplikacja: " + accessToken.getApplicationId();
s += "\nUżytkownik: " + accessToken.getUserId();
//s += "\nToken: " + accessToken.getToken();
s += "\nTermin ważności: " + accessToken.getExpires().toString();
s += "\nUprawnienia: ";
for(String permission : accessToken.getPermissions())
{
s += "\n\t" + permission;
}
}
return s;
}
Można teraz przygotować zawartość z obrazem:
Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
SharePhoto photo = new SharePhoto.Builder()
.setBitmap(bmp)
.build();
SharePhotoContent zawartośćObraz = new SharePhotoContent.Builder()
.addPhoto(photo)
.build();
i publikowanie:
shareDialog.show(zawartośćObraz);
7. Publikowanie złożonej zawartości
Uwaga! Wymaga zainstalowanej aplikacji Facebook
//mieszanie różnych zawartości
ShareContent zawartośćZłożona = new ShareMediaContent.Builder()
.addMedium(photo)
.addMedium(photo) //można dodawać różne zdjęcia i wideo
.build();
...
shareDialog.show(zawartośćZłożona); //to wymaga zainstalowanej aplikacji
Przycisk LIKE
-------------
1. Do pliku activity_main.xml dodajmy kontrolkę:
2. Na końcu onCreate dodajmy
LikeView likeView = (LikeView) findViewById(R.id.likeView);
likeView.setLikeViewStyle(LikeView.Style.STANDARD);
likeView.setAuxiliaryViewPosition(LikeView.AuxiliaryViewPosition.INLINE);
likeView.setObjectIdAndType(
"http://www.fizyka.umk.pl/~jacek/dydaktyka",
LikeView.ObjectType.PAGE);
Błędy? Zob. https://inthecheesefactory.com/blog/how-to-add-facebook-like-button-in-android-app/en
Przycisk Udostępniania
----------------------
To samo, co wcześniej, ale gotowy przycisk z przypisaną akcją.
1. Do pliku activity_main.xml dodajmy kontrolkę:
2. Na końcu onCreate dodajmy
ShareLinkContent zawartośćLink = new ShareLinkContent.Builder()
//.setContentDescription("Opis (wycofane)")
//.setContentTitle("Tytuł (wycofane)")
.setContentUrl(Uri.parse("http://www.fizyka.umk.pl/~jacek/dydaktyka"))
.setQuote(treśćWpisu.getText().toString())
.setShareHashtag(new ShareHashtag.Builder().setHashtag("#UMK").build())
.build();
ShareButton shareButton = (ShareButton)findViewById(R.id.shareButton);
shareButton.setShareContent(zawartośćLink);
Zadanie: Wysłać zdjęcie (zawartośćObraz) używając SendButton przez Facebook Messenger - analogicznie do ShareButton