Android y Facebook comparten intención
Estoy desarrollando una aplicación para Android y me interesa saber cómo se puede actualizar el estado del usuario de la aplicación desde dentro de la aplicación utilizando los intentos de compartir de Android.
Después de revisar el SDK de Facebook, parece que esto es bastante fácil de hacer, sin embargo, estoy interesado en permitir que el usuario lo haga a través de la ventana emergente Share Intent normal. visto aquí:
Probé el código de intención de compartir habitual, sin embargo, parece que ya no funciona para Facebook.
public void invokeShare(Activity activity, String quote, String credit) {
Intent shareIntent = new Intent(android.content.Intent.ACTION_SEND);
shareIntent.setType("text/plain");
shareIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, activity.getString(R.string.share_subject));
shareIntent.putExtra(android.content.Intent.EXTRA_TEXT, "Example text");
activity.startActivity(Intent.createChooser(shareIntent, activity.getString(R.string.share_title)));
}
ACTUALIZACIÓN: Después de investigar más, parece que es un error con la aplicación de Facebook que aún no se ha resuelto. ( error de Facebook ) Mientras tanto, parece que voy a tener que aguantar el comentario negativo "¡¡¡Compartir no funciona!!!" revisiones. Saludos facebook :*(
Aparentemente, Facebook ya no (a partir de 2014) te permite personalizar la pantalla para compartir, sin importar si simplemente estás abriendo la URL sharer.php o usando intents de Android de maneras más especializadas. Vea, por ejemplo, estas respuestas:
- "Sharer.php ya no permite personalizar".
- "Necesitas usar el SDK de Facebook para Android o el SDK de Easy Facebook para Android para compartir".
De todos modos, usando Intents simples, aún puedes compartir una URL, pero no ningún texto predeterminado con ella , como comentó billynomates . (Además, si no tiene una URL para compartir, simplemente iniciar la aplicación de Facebook con el cuadro de diálogo "Escribir publicación" (es decir, actualización de estado) vacío es igualmente fácil; use el código a continuación, pero omítalo EXTRA_TEXT
).
Esta es la mejor solución que he encontrado y que no implica el uso de ningún SDK de Facebook.
Este código abre la aplicación oficial de Facebook directamente si está instalada y, de lo contrario, vuelve a abrir sharer.php en un navegador. (La mayoría de las otras soluciones en esta pregunta muestran un enorme cuadro de diálogo "Completar acción usando..." que no es óptimo en absoluto).
String urlToShare = "https://stackoverflow.com/questions/7545254";
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
// intent.putExtra(Intent.EXTRA_SUBJECT, "Foo bar"); // NB: has no effect!
intent.putExtra(Intent.EXTRA_TEXT, urlToShare);
// See if official Facebook app is found
boolean facebookAppFound = false;
List<ResolveInfo> matches = getPackageManager().queryIntentActivities(intent, 0);
for (ResolveInfo info : matches) {
if (info.activityInfo.packageName.toLowerCase().startsWith("com.facebook.katana")) {
intent.setPackage(info.activityInfo.packageName);
facebookAppFound = true;
break;
}
}
// As fallback, launch sharer.php in a browser
if (!facebookAppFound) {
String sharerUrl = "https://www.facebook.com/sharer/sharer.php?u=" + urlToShare;
intent = new Intent(Intent.ACTION_VIEW, Uri.parse(sharerUrl));
}
startActivity(intent);
(Con respecto al com.facebook.katana
nombre del paquete, consulte el comentario de MatheusJardimB ).
El resultado se ve así en mi Nexus 7 (Android 4.4) con la aplicación de Facebook instalada:
La aplicación de Facebook no maneja los campos
EXTRA_SUBJECT
oEXTRA_TEXT
.
Aquí hay un enlace de error: https://developers.facebook.com/bugs/332619626816423
Gracias @billynomates:
La cuestión es que si pones una URL en el
EXTRA_TEXT
campo, funciona . Es como si estuvieran eliminando intencionalmente cualquier texto.
La forma habitual
La forma habitual de crear lo que estás solicitando es simplemente hacer lo siguiente:
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TEXT, "The status update text");
startActivity(Intent.createChooser(intent, "Dialog title text"));
Esto funciona sin ningún problema para mí.
La forma alternativa (tal vez)
El problema potencial al hacer esto es que también permite que el mensaje se envíe por correo electrónico, SMS, etc. El siguiente código es algo que estoy usando en una aplicación que permite al usuario enviarme un correo electrónico. -correo usando Gmail. Supongo que podrías intentar cambiarlo para que funcione sólo con Facebook.
No estoy seguro de cómo responde a errores o excepciones (supongo que eso ocurriría si Facebook no está instalado), por lo que es posible que tengas que probarlo un poco.
try {
Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
String[] recipients = new String[]{"e-mail address"};
emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, recipients);
emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "E-mail subject");
emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, "E-mail text");
emailIntent.setType("plain/text"); // This is incorrect MIME, but Gmail is one of the only apps that responds to it - this might need to be replaced with text/plain for Facebook
final PackageManager pm = getPackageManager();
final List<ResolveInfo> matches = pm.queryIntentActivities(emailIntent, 0);
ResolveInfo best = null;
for (final ResolveInfo info : matches)
if (info.activityInfo.packageName.endsWith(".gm") ||
info.activityInfo.name.toLowerCase().contains("gmail")) best = info;
if (best != null)
emailIntent.setClassName(best.activityInfo.packageName, best.activityInfo.name);
startActivity(emailIntent);
} catch (Exception e) {
Toast.makeText(this, "Application not found", Toast.LENGTH_SHORT).show();
}
Descubrí que solo puedes compartir Texto o Imagen , no ambos usando Intents
. El siguiente código comparte solo la imagen si existe, o solo el texto si la imagen no existe. Si desea compartir ambos, debe utilizar el SDK de Facebook desde aquí.
Si utiliza otra solución en lugar del código siguiente, no olvide especificar también el nombre del paquete com.facebook.lite , que es el nombre del paquete de Facebook Lite . No lo he probado, pero com.facebook.orca es el nombre del paquete de Facebook Messenger si también quieres apuntar a eso.
Puedes agregar más métodos para compartir con WhatsApp , Twitter ...
public class IntentShareHelper {
/**
* <b>Beware,</b> this shares only image if exists, or only text if image does not exits. Can't share both
*/
public static void shareOnFacebook(AppCompatActivity appCompatActivity, String textBody, Uri fileUri) {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TEXT,!TextUtils.isEmpty(textBody) ? textBody : "");
if (fileUri != null) {
intent.putExtra(Intent.EXTRA_STREAM, fileUri);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setType("image/*");
}
boolean facebookAppFound = false;
List<ResolveInfo> matches = appCompatActivity.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo info : matches) {
if (info.activityInfo.packageName.toLowerCase().startsWith("com.facebook.katana") ||
info.activityInfo.packageName.toLowerCase().startsWith("com.facebook.lite")) {
intent.setPackage(info.activityInfo.packageName);
facebookAppFound = true;
break;
}
}
if (facebookAppFound) {
appCompatActivity.startActivity(intent);
} else {
showWarningDialog(appCompatActivity, appCompatActivity.getString(R.string.error_activity_not_found));
}
}
public static void shareOnWhatsapp(AppCompatActivity appCompatActivity, String textBody, Uri fileUri){...}
private static void showWarningDialog(Context context, String message) {
new AlertDialog.Builder(context)
.setMessage(message)
.setNegativeButton(context.getString(R.string.close), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
})
.setCancelable(true)
.create().show();
}
}
Para obtener Uri de File, use la siguiente clase:
public class UtilityFile {
public static @Nullable Uri getUriFromFile(Context context, @Nullable File file) {
if (file == null)
return null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
try {
return FileProvider.getUriForFile(context, "com.my.package.fileprovider", file);
} catch (Exception e) {
e.printStackTrace();
return null;
}
} else {
return Uri.fromFile(file);
}
}
// Returns the URI path to the Bitmap displayed in specified ImageView
public static Uri getLocalBitmapUri(Context context, ImageView imageView) {
Drawable drawable = imageView.getDrawable();
Bitmap bmp = null;
if (drawable instanceof BitmapDrawable) {
bmp = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
} else {
return null;
}
// Store image to default external storage directory
Uri bmpUri = null;
try {
// Use methods on Context to access package-specific directories on external storage.
// This way, you don't need to request external read/write permission.
File file = new File(context.getExternalFilesDir(Environment.DIRECTORY_PICTURES), "share_image_" + System.currentTimeMillis() + ".png");
FileOutputStream out = new FileOutputStream(file);
bmp.compress(Bitmap.CompressFormat.PNG, 90, out);
out.close();
bmpUri = getUriFromFile(context, file);
} catch (IOException e) {
e.printStackTrace();
}
return bmpUri;
}
}
Para escribir FileProvider , utilice este enlace: https://github.com/codepath/android_guides/wiki/Sharing-Content-with-Intents