Android Open Source - Sushi-Shooter Transaction Receiver






From Project

Back to project page Sushi-Shooter.

License

The source code is released under:

GNU General Public License

If you think the Android project Sushi-Shooter listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * session M//w  ww.jav a 2  s  .c  o  m
 * Copyright 2012
 */
package com.sessionm;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.json.JSONException;
import org.json.JSONObject;

import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;

/* TransactionReceiver
 * 
 * * <P>A receiver to intercept, process, and store session M transactions.
 * Includes static methods for querying session M transactionData and generating odid ids (reference http://code.google.com/p/odinmobile/)  
 * 
 * USAGE: 
 * Put the following calls in the onCreate method of the application's MainActivity: 

        Context context = this.getActivityContext();

        TransactionReceiver.start(context);

 */

public class TransactionReceiver extends BroadcastReceiver{

    // The sessionm transaction url
    private static final String TARGET_URL = "https://ads.sessionm.com/transactions.json";


    /*
     * Reports the session M tracking Id if it was not initially sent during the initial intent call
     * @
     * @param  context   The context of the application.
     * @return void
     * 
     */    
    public static void start(Context context){

        Map<String, String> prefInfo  = retrieveTransactionInfo(context);
        
        if(prefInfo.size() == 0 || prefInfo.containsKey("sent") == true)
            return;
        
        String transactionId = prefInfo.get("transactionId");
        
        reportTransactionId(context,transactionId);
    }


    /*
     * Returns the transactionId and the original google analytics referrer string along with any extra parameters or null if the data does not exist
     * 
     * @param  context   The context of the application.
     * @return A hashmap populated with session M transaction info
     * 
     */    
    public static Map<String,String> retrieveTransactionInfo(Context context){

        SharedPreferences remotePrefs = context.getApplicationContext().getSharedPreferences("SMPREFS_FILE", Context.MODE_WORLD_READABLE|Context.MODE_WORLD_WRITEABLE);

        Map<String,?> prefData = remotePrefs.getAll();

        Iterator<?> entryIter = prefData.entrySet().iterator();

        HashMap<String,String> data = new HashMap<String,String>();

        while(entryIter.hasNext() == true){
            @SuppressWarnings("unchecked")
            Entry<String, ?> next = (Entry<String, ?>) entryIter.next();
            data.put(next.getKey(),next.getValue().toString());
        }

        return data;
    }




    /*
     * Returns the ODIN-1 String for the Android device. For devices that have a null
     * or invalid ANDROID_ID (such as the emulator), a null value will be returned.
     * 
     * This code is designed to be built against an Android API level 3 or greater,
     * but supports all Android API levels.
     * 
     * @param  context   the context of the application.
     * 
     * @return           the ODIN-1 string or null if the ANDROID_ID is invalid.
     */
    public static String getOdin(Context context){
        return ODIN.getODIN1(context);
    }


    /*
     * Reports the session M transaction to the server
     * 
     * This code is designed to be built against an Android API level 3 or greater,
     * but supports all Android API levels.
     * 
     * @param  String the session M transaction id
     * 
     * @return  boolean true if the transaction was successfully reported 
     */
    public static boolean reportTransactionId(Context context,String transactionId){

        HttpURLConnection conn = null;
        String agent = "Mozilla/4.0";
        String encodedData = "";
        if(transactionId == null || transactionId.length() == 0){
            // if there is no transaction id , generate an odin and send it up with the current app's package name
            transactionId = getOdin(context);
            encodedData = "id2=" + context.getApplicationContext().getPackageName() + ":" + URLEncoder.encode(transactionId);
        }else{
            encodedData = "id=" + URLEncoder.encode(transactionId);
        }
        String type = "application/x-www-form-urlencoded";
        try {
            URL url = new URL(TARGET_URL);
            conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("POST");
            conn.setRequestProperty( "User-Agent", agent );
            conn.setRequestProperty( "Content-Type", type );
            conn.addRequestProperty( "Content-Length",String.valueOf(encodedData.length()));
            conn.setDoInput(true);
            conn.setDoOutput(true);
            OutputStream os = conn.getOutputStream();
            os.write( encodedData.getBytes());
            int rc = conn.getResponseCode();
            
            if(rc >= 200 && rc < 300){
                
                
                DataInputStream br = new DataInputStream(conn.getInputStream());
                String line = "";
                String content = "";
                while((line = br.readLine()) != null )
                    content += line;

                JSONObject respJson = new JSONObject(content);
                if(respJson.optString("status").equalsIgnoreCase("ok") == true){
                    SharedPreferences remotePrefs = context.getApplicationContext().getSharedPreferences("SMPREFS_FILE", Context.MODE_WORLD_READABLE|Context.MODE_WORLD_WRITEABLE);
                    remotePrefs.edit().putString("sent", "true").commit();
                    return true;
                }
            }
        }
        catch( IOException e ){
            e.printStackTrace();
        } catch (JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return false;
    }


    private static HashMap<String,String> parseReferrer(String gaReferrerString){

        String referrerString = "";
        HashMap<String, String> referralParams = new HashMap<String, String> ();
        try {
            referrerString = URLDecoder.decode(gaReferrerString,"x-www-form-urlencoded");
            String[] params = referrerString.split("&"); 

            for (String param : params){
                String[] pair = param.split("="); // $NON-NLS-1$
                referralParams.put(pair[0], pair[1]);
            }
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }catch (ArrayIndexOutOfBoundsException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return referralParams;
    }

    @Override
    public void onReceive(Context context, Intent infoIntent) {

        if(infoIntent == null)
            return;
        Bundle extras = infoIntent.getExtras();
        String action = infoIntent.getAction();

        // if the intent is google analytics we set the referrer param and the transaction id to the analytics referrer as well
        if(action == null || action.equalsIgnoreCase("com.android.vending.INSTALL_REFERRER") == false )
            return;

        String transactionId = "undefined";
        String referrerStr = "";

        //grab the referrer parameter from the analytics tracking url
        if(extras.containsKey("referrer"))
            referrerStr = extras.getString("referrer"); 

        // forward the intent to other analytics receivers specified in the meta-data portion of this receivers xml
        forwardAnalyticsIntent(context,infoIntent); 

        HashMap<String,String> rParams =  parseReferrer(referrerStr);

        // If the analytics source is sessionm and an id is present (in the utm_content param) we process this intent
        if(rParams.containsKey("utm_source") == true && rParams.get("utm_source").equalsIgnoreCase("sessionm") && rParams.containsKey("utm_content") == true) 
            transactionId = rParams.get("utm_content");
        else
            return; 

        // store the transaction data into local preferences to retrieve it later
        storeSesssionMTransaction(context, referrerStr, transactionId); 

        // if the transaction was sent to the server, mark it so we don't re-send it
        reportTransactionId(context,transactionId);


    }


    private void storeSesssionMTransaction(Context context,String referrerString,String transactionId) {
        SharedPreferences remotePrefs = context.getApplicationContext().getSharedPreferences("SMPREFS_FILE", Context.MODE_WORLD_READABLE|Context.MODE_WORLD_WRITEABLE);
        Editor edit = remotePrefs.edit();
        edit.putString("referrer", referrerString);
        edit.putString("transactionId", transactionId);
        edit.commit();
    }

    private void forwardAnalyticsIntent(Context context,Intent analyticsIntent){

        try{

            ComponentName component = new ComponentName(context,this.getClass());

            PackageManager pm = context.getApplicationContext().getPackageManager();

            ActivityInfo receiverInfo = pm.getReceiverInfo(component, PackageManager.GET_META_DATA);

            Bundle metaData = receiverInfo.metaData;

            if(metaData != null){ // iterate through meta data in the receiver's xml and forward the analytics intent

                Set<String> keyset = metaData.keySet();
                Iterator<String> iter = keyset.iterator();

                while(iter.hasNext() == true){

                    String key = iter.next();
                    String alternateReceiver =  metaData.getString(key);
                    ((BroadcastReceiver)Class.forName(alternateReceiver).newInstance()).onReceive(context, analyticsIntent);

                }
            }

        }catch(NameNotFoundException e){
            e.printStackTrace();
        } catch (NullPointerException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InstantiationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    private static class ODIN {
        private final static String TAG = "ODIN";
        private final static String SHA1_ALGORITHM = "SHA-1";
        private final static String CHAR_SET = "iso-8859-1";


        public static String getODIN1(Context context) {
            String androidId;
            try {
                androidId = Settings.System.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
            } catch (Exception e) {

                // In Android API levels 1-2, Settings.Secure wasn't implemented.
                // Fall back to deprecated methods.
                try {
                    androidId = Settings.System.getString(context.getContentResolver(), Settings.System.ANDROID_ID);
                } catch (Exception e1) {
                    Log.i(TAG, "Error generating ODIN-1: ", e1);
                    return null;
                }
            }

            return SHA1(androidId);
        }

        private static String convertToHex(byte[] data) {
            StringBuffer buf = new StringBuffer();
            for (int i = 0; i < data.length; i++) {
                int halfbyte = (data[i] >>> 4) & 0x0F;
                int two_halfs = 0;
                do {
                    if ((0 <= halfbyte) && (halfbyte <= 9))
                        buf.append((char) ('0' + halfbyte));
                    else
                        buf.append((char) ('a' + (halfbyte - 10)));
                    halfbyte = data[i] & 0x0F;
                } while(two_halfs++ < 1);
            }
            return buf.toString();
        }

        private static String SHA1(String text) {
            try {
                MessageDigest md;
                md = MessageDigest.getInstance(SHA1_ALGORITHM);
                byte[] sha1hash = new byte[40];
                md.update(text.getBytes(CHAR_SET), 0, text.length());
                sha1hash = md.digest();

                return convertToHex(sha1hash);
            } catch (Exception e) {
                Log.i(TAG, "Error generating generating SHA-1: ", e);
                return null;
            }
        }

    }
}




Java Source Code List

com.sessionm.TransactionReceiver.java
net.gamecloud.sushishooter.BmpWrap.java
net.gamecloud.sushishooter.BubbleFont.java
net.gamecloud.sushishooter.BubbleManager.java
net.gamecloud.sushishooter.BubbleSprite.java
net.gamecloud.sushishooter.Compressor.java
net.gamecloud.sushishooter.FrozenBubble.java
net.gamecloud.sushishooter.FrozenGame.java
net.gamecloud.sushishooter.GameScreen.java
net.gamecloud.sushishooter.GameView.java
net.gamecloud.sushishooter.ImageSprite.java
net.gamecloud.sushishooter.LaunchBubbleSprite.java
net.gamecloud.sushishooter.LevelManager.java
net.gamecloud.sushishooter.PenguinSprite.java
net.gamecloud.sushishooter.SoundManager.java
net.gamecloud.sushishooter.Sprite.java