I had the same need as you, accessing images from a public profile on Instagram in the Android Application.
But one thing I did differently was to create a WebService
which from time to time queries the Media API and updates the database. But the access core should look good.
I did this because I do not know if it's worth to leave the Client ID
in the application, for security reasons, someone can spy on the requests and get the Client ID
that your application is using, is invalid.
The code is a bit more complex, because I've tried to normalize the consumption of various social networking APIs, I'll just put the specific part of Instagram.
To mount the access URI to Client ID
grams of instagram I did:
public String getUri(String instagramUserId, String token, int amount) throws UnsupportedEncodingException {
StringBuilder uri = new StringBuilder("https://api.instagram.com/v1");
// instagramUserId é uma variável local com o ID do usuário de perfil público
// Pode ser obtido nesse site: http://jelled.com/instagram/lookup-user-id
// token é o Client ID do aplicativo
// amount é a quantidade de registros que devem ser retornadas
uri.append("/users/").append(instagramUserId)
.append("/media/recent?client_id=").append(URLEncoder.encode(token, "UTF-8"))
.append("&count=").append(Integer.toString(amount));
return uri.toString();
}
With this URI I made a WebService
for the Instagram endpoint, as below:
@Override
public List<JSONObject> fetchInstagram(String instagramUserId, String token, int amount) {
try {
String uri = getUri(instagramUserId, token, amount);
if(uri == null) {
return Collections.EMPTY_LIST;
}
// Inicializa um cliente Http
HttpClient httpClient = HttpClientBuilder.create().build();
// Especifica o método a ser executado, GET como especificado pela documentacao do Instagram
HttpGet get = new HttpGet(uri);
// Definindo o Charset da resposta, a fim de evitar problemas com encoding
// Definindo que o cliente aceita codificação gzip, para reduzir o gasto de banda do dispositivo.
get.addHeader("Accept-Encoding", "gzip");
get.addHeader("Accept-Charset", "UTF-8");
System.out.println("Making request to " + uri);
// Executa a requisicao e espera pela resposta
HttpResponse response = httpClient.execute(get);
// Se o Instagram nao respondeu com codigo 200 (OK), entao loga o erro
if(response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
System.out.println(EntityUtils.toString(response.getEntity(), Charset.forName("UTF-8")));
return null;
}
// Extrai a resposta em formato String
String responseString = EntityUtils.toString(response.getEntity(), Charset.forName("UTF-8"));
// Retorna a lista de registros de midia do usuario
return parseResponse(responseString);
} catch (MalformedURLException | ProtocolException e) {
e.printStackTrace();
return null;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
// Aqui poderia ser retornado o próprio JSONArray com os registros
public List<JSONObject> parseResponse(String response) {
// Transforma a resposta String em JSON, para poder manipular
JSONObject jsonResponse = new JSONObject(response);
// Atributo do JSON que contem a lista de registros obtidos do usuario
JSONArray registros = jsonResponse.getJSONArray("data");
List<JSONObject> objetos = new ArrayList<JSONObject>();
for(int i = 0; i < registros.length(); ++i) {
JSONObject o = registros.getJSONObject(i);
// Faz uma logica com o registro em si, filtragem, normalizacao, ou outro qualquer
objetos.add(o);
}
return registros;
}
To use, just do:
public void callInstagram() {
String token = "SEU_CLIENT_D";
String instagramUserId = "USER_ID";
int amount = 100;
List<JSONObject> registros = fetchInstagram(instagramUserId, token, amount);
// Processa os registros, levando em conta o tipo e as resolucoes das midias.
}
In this solution I ended up using the Apache HttpRequest
fault API (to use the HttpClient, HttpGet, and HttpClientBuilder class), which can be obtained at this address: link . There is migration for Android at this address: link .
An example of an Instagram JSON response is:
{
"data": [{
"comments": {
"data": [],
"count": 0
},
"caption": {
"created_time": "1296710352",
"text": "Inside le truc #foodtruck",
"from": {
"username": "kevin",
"full_name": "Kevin Systrom",
"type": "user",
"id": "3"
},
"id": "26621408"
},
"likes": {
"count": 15,
"data": [{
"username": "mikeyk",
"full_name": "Mike Krieger",
"id": "4",
"profile_picture": "..."
}, {...subset of likers...}]
},
"link": "http://instagr.am/p/BWrVZ/",
"user": {
"username": "kevin",
"profile_picture": "http://distillery.s3.amazonaws.com/profiles/profile_3_75sq_1295574122.jpg",
"id": "3"
},
"created_time": "1296710327",
"images": {
"low_resolution": {
"url": "http://distillery.s3.amazonaws.com/media/2011/02/02/6ea7baea55774c5e81e7e3e1f6e791a7_6.jpg",
"width": 306,
"height": 306
},
"thumbnail": {
"url": "http://distillery.s3.amazonaws.com/media/2011/02/02/6ea7baea55774c5e81e7e3e1f6e791a7_5.jpg",
"width": 150,
"height": 150
},
"standard_resolution": {
"url": "http://distillery.s3.amazonaws.com/media/2011/02/02/6ea7baea55774c5e81e7e3e1f6e791a7_7.jpg",
"width": 612,
"height": 612
}
},
"type": "image",
"users_in_photo": [],
"filter": "Earlybird",
"tags": ["foodtruck"],
"id": "22721881",
"location": {
"latitude": 37.778720183610183,
"longitude": -122.3962783813477,
"id": "520640",
"street_address": "",
"name": "Le Truc"
}
},
{
"videos": {
"low_resolution": {
"url": "http://distilleryvesper9-13.ak.instagram.com/090d06dad9cd11e2aa0912313817975d_102.mp4",
"width": 480,
"height": 480
},
"standard_resolution": {
"url": "http://distilleryvesper9-13.ak.instagram.com/090d06dad9cd11e2aa0912313817975d_101.mp4",
"width": 640,
"height": 640
},
"comments": {
"data": [{
"created_time": "1279332030",
"text": "Love the sign here",
"from": {
"username": "mikeyk",
"full_name": "Mikey Krieger",
"id": "4",
"profile_picture": "http://distillery.s3.amazonaws.com/profiles/profile_1242695_75sq_1293915800.jpg"
},
"id": "8"
},
{
"created_time": "1279341004",
"text": "Chilako taco",
"from": {
"username": "kevin",
"full_name": "Kevin S",
"id": "3",
"profile_picture": "..."
},
"id": "3"
}],
"count": 2
},
"caption": null,
"likes": {
"count": 1,
"data": [{
"username": "mikeyk",
"full_name": "Mikeyk",
"id": "4",
"profile_picture": "..."
}]
},
"link": "http://instagr.am/p/D/",
"created_time": "1279340983",
"images": {
"low_resolution": {
"url": "http://distilleryimage2.ak.instagram.com/11f75f1cd9cc11e2a0fd22000aa8039a_6.jpg",
"width": 306,
"height": 306
},
"thumbnail": {
"url": "http://distilleryimage2.ak.instagram.com/11f75f1cd9cc11e2a0fd22000aa8039a_5.jpg",
"width": 150,
"height": 150
},
"standard_resolution": {
"url": "http://distilleryimage2.ak.instagram.com/11f75f1cd9cc11e2a0fd22000aa8039a_7.jpg",
"width": 612,
"height": 612
}
},
"type": "video",
"users_in_photo": null,
"filter": "Vesper",
"tags": [],
"id": "363839373298",
"user": {
"username": "kevin",
"full_name": "Kevin S",
"profile_picture": "http://distillery.s3.amazonaws.com/profiles/profile_3_75sq_1295574122.jpg",
"id": "3"
},
"location": null
},
]
}
You will need to see which fields of each object that make up the response is necessary, and take into account that for some media types (image in this case), it provides various resolutions, which can be used on different devices (tablets or smartphone).