Informar de la instalación de la aplicación Android de nuevo a facebook sin usar su api
Desde mi aplicación de Android, me gustaría publicar su instalación de nuevo en facebook para permitir el seguimiento de conversiones para sus anuncios de instalación de aplicaciones para móviles, pero me gustaría hacerlo sin usar su api.
Así que en lugar de hacer
- Obtener la foto de la portada utilizando la API de Facebook
- Deep linking en Android no inicia la aplicación y redirige a Android market market
- Cómo abrir mi aplicación Android nativa desde una entrada en Facebook
- Cómo publicar a la pared facebook android-sdk: 4.0.0
- ¿Por qué la aplicación Android de Facebook se desplaza tan suavemente
com.facebook.Settings.publishInstall(context, appId);
Me gustaría enviar una solicitud HTTP con los parámetros necesarios a alguna URL.
EDITAR:
He registrado las dos solicitudes que se envían a facebook para publicar la instalación de la aplicación y se ven así:
Solicitud:
GET /[app id]?format=json&sdk=android&fields=supports_attribution HTTP/1.1 User-Agent: FBAndroidSDK.3.0.0.b Content-Type: multipart/form-data; boundary=3i2ndDfv2rTHiSisAbouNdArYfORhtTPEefj3q2f Host: graph.facebook.com Connection: Keep-Alive Accept-Encoding: gzip
Respuesta:
HTTP/1.1 200 OK Access-Control-Allow-Origin: * Cache-Control: private, no-cache, no-store, must-revalidate Content-Type: text/javascript; charset=UTF-8 ETag: "24ea6554744eece05b90dd2e65af63277cdcaf53" Expires: Sat, 01 Jan 2000 00:00:00 GMT Pragma: no-cache X-FB-Rev: 658994 X-FB-Debug: P2GE3fDVAnRJh62rBS5WXD4ce1hTy8Pwvjq5rT/I+TI= Date: Tue, 30 Oct 2012 11:37:09 GMT Connection: keep-alive Content-Length: 52 {"supports_attribution":true,"id":"[app id]"}
Solicitud:
POST /[app id]/activities?format=json&sdk=android&migration_bundle=fbsdk%3A20120913 HTTP/1.1 User-Agent: FBAndroidSDK.3.0.0.b Content-Type: multipart/form-data; boundary=3i2ndDfv2rTHiSisAbouNdArYfORhtTPEefj3q2f Host: graph.facebook.com Connection: Keep-Alive Transfer-Encoding: chunked Accept-Encoding: gzip 261 --3i2ndDfv2rTHiSisAbouNdArYfORhtTPEefj3q2f Content-Disposition: form-data; name="format" json --3i2ndDfv2rTHiSisAbouNdArYfORhtTPEefj3q2f Content-Disposition: form-data; name="sdk" android --3i2ndDfv2rTHiSisAbouNdArYfORhtTPEefj3q2f Content-Disposition: form-data; name="migration_bundle" fbsdk:20120913 --3i2ndDfv2rTHiSisAbouNdArYfORhtTPEefj3q2f Content-Disposition: form-data; name="attribution" ab175007-2725-464f-a111-b8b1a92bf1dd --3i2ndDfv2rTHiSisAbouNdArYfORhtTPEefj3q2f Content-Disposition: form-data; name="event" MOBILE_APP_INSTALL --3i2ndDfv2rTHiSisAbouNdArYfORhtTPEefj3q2f 0
Respuesta:
HTTP/1.1 200 OK Access-Control-Allow-Origin: * Cache-Control: private, no-cache, no-store, must-revalidate Content-Type: text/javascript; charset=UTF-8 Expires: Sat, 01 Jan 2000 00:00:00 GMT Pragma: no-cache X-FB-Rev: 658994 X-FB-Debug: +0GWQ4cu+tFeAg3QEuwYGx+HAt7t37itzxEYBaTZF8U= Date: Tue, 30 Oct 2012 11:38:33 GMT Connection: keep-alive Content-Length: 4 true
He incluido una versión reducida de la api de Facebook en mi aplicación que no puede hacer nada más, pero simplemente envíe esas dos solicitudes. Lo probaré e informará sobre cómo funciona.
De manera óptima, me gustaría enviar las solicitudes desde un servidor y no desde el teléfono en absoluto.
- Compartir texto en facebook con la intención de compartir de Android
- Android - ¿Cómo puedo detectar si el usuario ha decidido compartir con Facebook o Twitter con la intención?
- ¿Hay alguna forma de obtener hash clave de APK firmado?
- Inicio de sesión de facebook con fragmento
- Problema problemático para la integración de FaceBook
- Cómo obtener notificación de estado en tiempo real con Facebook SDK a través de escuchas
- Cómo confirmar que Android Share Intent se ha completado correctamente
- Android AccountKit.getCurrentAccount devuelve "Las llamadas de la API desde el servidor requieren un argumento appsecret_proof"
Usted puede hacer esto con llamada simple
FacebookHelper.appInstall(this.getApplicationContext(), "<com.your.package>", "<your facebook app id>");
Y la biblioteca a continuación.
Recuerda que solo puedes realizar el seguimiento de la aplicación si la aplicación de facebook está instalada; entonces tienes attributionId. Si desea enviar esta solicitud en el servidor, tiene que enviar atributionId a su servidor.
import android.content.ContentResolver; import android.content.Context; import android.database.Cursor; import android.net.Uri; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpRequestBase; import org.apache.http.entity.mime.HttpMultipartMode; import org.apache.http.entity.mime.MultipartEntity; import org.apache.http.entity.mime.content.StringBody; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.protocol.HTTP; import java.io.IOException; import java.nio.charset.Charset; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; public class FacebookHelper { private static final Uri ATTRIBUTION_ID_CONTENT_URI = Uri.parse("content://com.facebook.katana.provider.AttributionIdProvider"); private static final String ATTRIBUTION_ID_COLUMN_NAME = "aid"; private static final String USER_AGENT = "FBAndroidSDK/3.5.0"; private final DefaultHttpClient mHttpClient; private final String mApplicationPackage; private final String mApplicationId; private FacebookHelper(String applicationPackage, String applicationId) { checkNotNull(applicationPackage); checkNotNull(applicationId); mApplicationPackage = applicationPackage; mApplicationId = applicationId; mHttpClient = new DefaultHttpClient(); } private static String getAttributionId(ContentResolver cr) { checkNotNull(cr); final String [] projection = {ATTRIBUTION_ID_COLUMN_NAME}; final Cursor cursor = cr.query(ATTRIBUTION_ID_CONTENT_URI, projection, null, null, null); if (cursor == null) { return null; } try { if (!cursor.moveToFirst()) { return null; } final int attributionColumnIndex = cursor.getColumnIndex(ATTRIBUTION_ID_COLUMN_NAME); if (attributionColumnIndex < 0) { return null; } return cursor.getString(attributionColumnIndex); } finally { cursor.close(); } } public static void appInstall(Context applicationContext, String applicationPackage, String applicationId) throws IOException { checkNotNull(applicationContext); checkNotNull(applicationPackage); checkNotNull(applicationId); final ContentResolver cr = applicationContext.getContentResolver(); final String attributionId = getAttributionId(cr); if (attributionId == null) { // we can not send anything if facebook app is not installed return; } final FacebookHelper facebookHelper = new FacebookHelper(applicationPackage, applicationId); facebookHelper.appInstall(attributionId); } private void appInstall(String attribution) throws IOException { checkNotNull(attribution); String url = String.format("https://graph.facebook.com/%s/activities", mApplicationId); MultipartEntity entity = new MultipartEntity( HttpMultipartMode.BROWSER_COMPATIBLE); Charset charset = Charset.forName(HTTP.UTF_8); entity.addPart("sdk", new StringBody("android", charset)); entity.addPart("format", new StringBody("json", charset)); entity.addPart("event", new StringBody("MOBILE_APP_INSTALL", charset)); entity.addPart("attribution", new StringBody(attribution, charset)); entity.addPart("auto_publish", new StringBody("false", charset)); entity.addPart("application_tracking_enabled", new StringBody("true", charset)); entity.addPart("migration_bundle", new StringBody("fbsdk:20130708", charset)); entity.addPart("application_package_name", new StringBody(mApplicationPackage, charset)); HttpEntityEnclosingRequestBase request = new HttpPost(url); setupDefaultHeaders(request); request.setEntity(entity); HttpResponse response = getHttpClient().execute(request); validateResponseCode(response, HttpStatus.SC_OK); } private void validateResponseCode(HttpResponse response, int expectedStatusCode) throws IOException { checkNotNull(response); checkArgument(expectedStatusCode != HttpStatus.SC_UNPROCESSABLE_ENTITY); checkArgument(expectedStatusCode != HttpStatus.SC_NOT_FOUND); int statusCode = response.getStatusLine().getStatusCode(); if (statusCode != expectedStatusCode) { throw new IOException("Wrong response code: "+ "expected <" +expectedStatusCode +"> was <" +statusCode+">"); } } private HttpClient getHttpClient() { return mHttpClient; } private void setupDefaultHeaders(HttpRequestBase request) { checkNotNull(request); request.setHeader("Accept", "application/json"); request.setHeader("User-Agent", USER_AGENT); } }
Esta biblioteca utiliza guayaba checkArgument y checkNotNull si no usas guayaba solo puedes saltar esas líneas.
No es posible hacerlo sin integrar nuestro SDK. Para los anuncios de instalación de aplicaciones, el SDK debe estar integrado con tu aplicación. Si vas al panel de control de la aplicación> Promocionar> Feed de Android, hay un mensaje que indica:
Nota: esto solo es efectivo si integraste el SDK de Facebook para Android. Se te cobrará cada vez que alguien vea tu anuncio.
Terminé publicando la instalación de nuevo a facebook desde mi aplicación, usando esta versión despojada de su api:
package de.techunity.fancy.facebook.publishinstall; import org.json.JSONException; import android.content.ContentResolver; import android.content.Context; import android.content.SharedPreferences; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.util.Log; import com.facebook.android.Util; public class InstallPublisher { private static final Uri ATTRIBUTION_ID_CONTENT_URI = Uri.parse("content://com.facebook.katana.provider.AttributionIdProvider"); private static final String ATTRIBUTION_ID_COLUMN_NAME = "aid"; private static final String ATTRIBUTION_PREFERENCES = "com.facebook.sdk.attributionTracking"; private static final String PUBLISH_ACTIVITY_PATH = "%s/activities"; private static final String MOBILE_INSTALL_EVENT = "MOBILE_APP_INSTALL"; private static final String SUPPORTS_ATTRIBUTION = "supports_attribution"; private static final String APPLICATION_FIELDS = "fields"; private static final String ANALYTICS_EVENT = "event"; private static final String ATTRIBUTION_KEY = "attribution"; /** * Manually publish install attribution to the facebook graph. Internally handles tracking repeat calls to prevent * multiple installs being published to the graph. * @param context * @return returns false on error. Applications should retry until true is returned. Safe to call again after * true is returned. */ public static boolean publishInstall(final Context context, final String applicationId) { try { if (applicationId == null) { return false; } final String attributionId = InstallPublisher.getAttributionId(context.getContentResolver()); final SharedPreferences preferences = context.getSharedPreferences(ATTRIBUTION_PREFERENCES, Context.MODE_PRIVATE); final String pingKey = applicationId+"ping"; long lastPing = preferences.getLong(pingKey, 0); if (lastPing == 0 && attributionId != null) { new Thread(new Runnable() { @Override public void run() { try { Bundle supportsAttributionParams = new Bundle(); supportsAttributionParams.putString(APPLICATION_FIELDS, SUPPORTS_ATTRIBUTION); Request pingRequest = Request.newGraphPathRequest(applicationId, null); pingRequest.setParameters(supportsAttributionParams); GraphObject supportResponse = pingRequest.executeAndWait().getGraphObject(); Object doesSupportAttribution = supportResponse.getProperty(SUPPORTS_ATTRIBUTION); if (!(doesSupportAttribution instanceof Boolean)) { throw new JSONException(String.format( "%s contains %s instead of a Boolean", SUPPORTS_ATTRIBUTION, doesSupportAttribution)); } if ((Boolean)doesSupportAttribution) { GraphObject publishParams = (GraphObject) GraphObjectWrapper.createGraphObject(); publishParams.setProperty(ANALYTICS_EVENT, MOBILE_INSTALL_EVENT); publishParams.setProperty(ATTRIBUTION_KEY, attributionId); String publishUrl = String.format(PUBLISH_ACTIVITY_PATH, applicationId); Request publishRequest = Request.newPostRequest(publishUrl, publishParams, null); publishRequest.executeAndWait(); // denote success since no error threw from the post. SharedPreferences.Editor editor = preferences.edit(); editor.putLong(pingKey, System.currentTimeMillis()); editor.commit(); } } catch (Exception e) { Log.d("fancy", "Couldn't publish publish install to facebook", e); } finally { Log.d("fancy", "Publish install to facebook thread completed"); } } }, "facebook publish install thread").start(); } return true; } catch (Exception e) { // if there was an error, fall through to the failure case. Util.logd("Facebook-publish", e.getMessage()); } return false; } public static String getAttributionId(ContentResolver contentResolver) { String [] projection = {ATTRIBUTION_ID_COLUMN_NAME}; Cursor c = contentResolver.query(ATTRIBUTION_ID_CONTENT_URI, projection, null, null, null); if (c == null || !c.moveToFirst()) { return null; } String attributionId = c.getString(c.getColumnIndex(ATTRIBUTION_ID_COLUMN_NAME)); c.close(); return attributionId; } }
- ¿Cómo destruir y recrear una escena en andengine correctamente?
- Resaltar texto en varios controles EditText simultáneamente