fr.outadev.skinswitch.MojangAccountSkin.java Source code

Java tutorial

Introduction

Here is the source code for fr.outadev.skinswitch.MojangAccountSkin.java

Source

/*
 * SkinSwitch - MojangAccountSkin
 * Copyright (C) 2014-2015  Baptiste Candellier
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package fr.outadev.skinswitch;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Base64;

import com.github.kevinsawicki.http.HttpRequest;

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

import java.io.IOException;
import java.util.Date;

/**
 * This type of skin is linked to a Minecraft player's UUID.
 * It will be downloaded as a copy of the player's skin, and will be refreshed in the same way.
 *
 * @author outadoc
 */
public class MojangAccountSkin extends BasicSkin {

    public static final String MOJANG_API_URL = "https://api.mojang.com/users/profiles/minecraft/";
    public static final String SESSION_API_URL = "https://sessionserver.mojang.com/session/minecraft/profile/";

    private static final long serialVersionUID = -276245776664028707L;

    private String uuid;

    public MojangAccountSkin(int id, String name, String description, Date creationDate, String uuid) {
        super(id, name, description, creationDate);
        setUuid(uuid);
    }

    public MojangAccountSkin(String name, String description, Date creationDate, String uuid) {
        super(name, description, creationDate);
        setUuid(uuid);
    }

    public String getUuid() {
        return uuid;
    }

    public void setUuid(String uuid) {
        this.uuid = uuid;
    }

    @Override
    public void downloadSkinFromSource(Context context) throws HttpRequest.HttpRequestException, IOException {
        if (getUuid() == null) {
            return;
        }

        //we have to request a file on Mojang's server if we wanna retrieve the player's skin from his UUID.
        String body = HttpRequest.get(SESSION_API_URL + getUuid()).useCaches(false).body();

        if (body == null) {
            throw new HttpRequest.HttpRequestException(new IOException("Response to get the skin URL was empty."));
        }

        //we're expecting a JSON document that looks like this:
        /*
           {
         ...
         "properties": [
             {
                 "name": "textures",
                 "value": "<base64 string>"
             }
         ]
           }
         */

        try {
            //trying to reach the properties.value string
            JSONObject obj = new JSONObject(body);
            JSONArray properties = obj.getJSONArray("properties");

            if (properties != null) {
                for (int i = 0; i < properties.length(); i++) {
                    if (properties.getJSONObject(i).getString("name").equals("textures")) {
                        //once that string is reached, we have to decode it: it's in base64
                        String base64info = properties.getJSONObject(i).getString("value");
                        JSONObject textureInfo = new JSONObject(
                                new String(Base64.decode(base64info, Base64.DEFAULT)));

                        //the decoded string is also a JSON document, so we parse that. should look like this:
                        /*
                           {
                               ...
                               "textures": {
                         "SKIN": {
                             "url": "<player skin URL>"
                         },
                         ...
                               }
                           }
                         */

                        //we want to retrieve the textures.SKIN.url string. that's the skin's URL. /FINALLY/.
                        String url = textureInfo.getJSONObject("textures").getJSONObject("SKIN").getString("url");

                        if (url != null) {
                            //download the skin from the provided URL
                            byte[] response = HttpRequest.get(url).useCaches(true).bytes();

                            if (response == null) {
                                throw new HttpRequest.HttpRequestException(
                                        new IOException("Couldn't download " + this));
                            }

                            //decode the bitmap and store it
                            Bitmap bmp = BitmapFactory.decodeByteArray(response, 0, response.length);

                            if (bmp != null) {
                                deleteAllCacheFilesFromFilesystem(context);
                                saveRawSkinBitmap(context, bmp);
                                bmp.recycle();
                            }
                        }
                    }
                }
            }
        } catch (JSONException e) {
            throw new HttpRequest.HttpRequestException(
                    new IOException("The response from Mojang was invalid. Woops."));
        }
    }

    /**
     * Checks if the skin's source is a valid skin.
     * Also sets the skin's linked player UUID if it's valid.
     *
     * @param username the username to check the validity of
     * @return true if it's valid, false if it's not
     */
    @Override
    public boolean validateSource(String username) {
        if (username != null && !username.isEmpty()) {
            String body = HttpRequest.get(MOJANG_API_URL + username).useCaches(true).body();

            if (body != null) {
                try {
                    JSONObject obj = new JSONObject(body);
                    setUuid(obj.getString("id"));

                    return true;
                } catch (JSONException e) {
                    return false;
                }
            }
        }

        return false;
    }

}