I had the same need as you, access the images of a public profile on Instagram on Android App.
But one thing I did differently was create a WebService
that from time to time queries the Media API and updates the database. But the core of the access should be very similar.
I did it because I don’t know if it’s worth leaving the Client ID
in the app, for security reasons, someone can spy on the requests and catch the Client ID
that your application is using, being able to make this Client ID
become invalid.
The code is a little more complex, because I tried to normalize the consumption of various social media API’s, I will put only the specific part of Instagram.
To mount the URI to access the WebService
from 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 one HttpRequest
to 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 API of HttpComponents
Apache (to use the Httpclient, Httpget, and Httpclientbuilder class), which can be obtained at this address: http://hc.apache.org/. There is the migration to Android at this address: http://hc.apache.org/httpcomponents-client-4.3.x/android-port.html.
An example of Instagram’s 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 answer is needed, and take into consideration that for some media types (image in this case), it provides multiple resolutions, which can be used on different devices (tablets or smartphone).
To
CALLBACK_URL
is the link from a page of your server that ends the Oauth process by getting the correct token? Or are you using a fake url just to extract the token from the url? Another question, registered thisCALLBACK_URL
on your Instagram developer account?– Wakim
I am using a fake URL and registered this URL there in the Instagram developer account yes. The error I am getting is
{"code": 403, "error_type": "OAuthForbiddenException", "error_message": "Implicit authentication is disabled"}
Actually I would like to display the public photos of a user without showing this Instagram login screen.– João Paulo Fricks
Ah, I get it... you’re using Implicit Flow, I didn’t know there was such a form of authentication. Take a look at the developer panel of Instagram, if the checkbox of
Disable implicit OAuth
is unchecked for your app.– Wakim
So, right after I posted the answer to your question, I went there and cleared that option and it worked. But funny that I’m testing on AVD and on a tablet from Samsung. On AVD is "correct", but on my tablet my App closes.
– João Paulo Fricks
Put the USB cable and check on Logcat which was the exception that occurred.
– Wakim
You know how to upload photos of a particular Instagram user without having to do this authentication, or better, that this authentication runs in the background without having to type user/password?
– João Paulo Fricks
You can only do this if the profile is public (https://help.instagram.com/116024195217477/). I used the http://instagram.com/developer/endpoints/users/#get_users_media_recent, the
access_token
in case it was my API_KEY.– Wakim
Yes, the idea is only for public profile. It would be as you exemplify how you use this method?
– João Paulo Fricks
Okay, I’m going to take a code that I used for the same purpose and create a response.
– Wakim