When the user clicks this button the app should retrieve the image from the web. It should do this in a separate thread and When the image is downloaded it should be displayed on the same Screen using ImageView.I can't seem to get it to work but I feel like I'm really close can anyone help me out please? Thanks!
My Manifest File
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.stephen.asyncdownloadimageurl">
<uses-permission android:name="android.permission.INTERNET">
</uses-permission>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
My XML FIle
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ImageView
android:id="#+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="#android:drawable/alert_light_frame"
android:layout_marginBottom="146dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true" />
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="#+id/imageView"
android:layout_centerHorizontal="true"
android:layout_marginBottom="91dp" />
<EditText
android:id="#+id/editText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="#+id/button"
android:layout_centerHorizontal="true"
android:layout_marginBottom="51dp"
android:ems="10" />
My Jave File
public class MainActivity extends AppCompatActivity {
Button btn;
EditText et;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = (Button) findViewById(R.id.button);
et = (EditText) findViewById(R.id.editText);
btn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
try {
URL url = new URL(et.getText().toString());
new MyDownloadTask().execute(url);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
private class MyDownloadTask extends AsyncTask<URL, Integer, Bitmap> {
#Override
protected Bitmap doInBackground(URL... params) {
URL url = params[0];
Bitmap bitmap = null;
try {
URLConnection connection = url.openConnection();
connection.connect();
InputStream is = connection.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
bitmap = BitmapFactory.decodeStream(bis);
bis.close();
is.close();
} catch (Exception e) {
e.printStackTrace();
return null;
}
return bitmap;
}
#Override
protected void onPostExecute(Bitmap bitmap) {
if (bitmap != null) {
ImageView myImage = (ImageView) findViewById(R.id.imageView);
myImage.setImageBitmap(bitmap);
} else {
Toast.makeText(getApplicationContext(), "Failed to Download Image", Toast.LENGTH_LONG).show();
}
}
}
}
Use special android libraries like Glide or Picasso to load images. It's really easy to use it, they have disk/memory cache, you can load image in separate thread without using complex solutions.
As you mentionned in a comment, your image is at this url
http://tny.im/ayy
This url does not point to an image. It points to a redirects, (http status 301).
It is possible that your connection is not following redirects.
You can instruct the connection to follow the redirection by:
((HttpURLConnection) connection).setInstanceFollowRedirects(true);
Ok so here is my thoughts after talking in the comments
1) I copied your code and xml EXACTLY as you posted and it WORKS fine for me, with that said I want to add a few things
EDIT: not sure if this matters but these were my imports
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;
import java.io.BufferedInputStream;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
I think it could be a combination of these possibilities
2) make sure your url is ok, make sure you add the http or https part. make sure your auto correct does not add anything (mine added a period at the end). since this is the only part I can't test, I feel like this could be it
3) Log everything, log the url right before its passed into your URL object just to be sure it is correct, look for ANY exceptions
4) the toast will not show up if url is wrong, if url can't parse a valid URL ( like mentioned earlier), it will be caught in the try catch surrounding the URL object being created and will not call the async task (happen to me when I put fake url in and I got exception, so try keep an eye out)
EDIT: for number 4, i got exception for incorrect protocol (left out the http) but if link was wrong then yes, toast showed up
5) try another image, you never know :D
EDIT: try this with Glide,
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = (Button) findViewById(R.id.button);
et = (EditText) findViewById(R.id.editText);
btn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
try {
Glide.with(MainActivity.this)
.load(et.getText().toString())
.into((ImageView) findViewById(R.id.imageView));
} catch (Exception e) {
e.printStackTrace();
}
}
no need for async
and one more solution without Glide
#Override
protected Bitmap doInBackground(URL... params) {
URL url = params[0];
HttpURLConnection connection = null;
Bitmap bitmap = null;
try {
connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
BufferedInputStream bis = new BufferedInputStream(input);
bitmap = BitmapFactory.decodeStream(bis);
bis.close();
input.close();
} catch (IOException e) {
e.printStackTrace();
}
return bitmap;
}
// Add following dependecny for glide
compile 'com.github.bumptech.glide:glide:3.7.0'
new LoadImageFromUrlTask().execute(imageURL);
public class LoadImageFromUrlTask extends AsyncTask<String, Void, Bitmap> {
String downloadPath = "";
String sdCardBasePath = Environment.getExternalStorageDirectory().toString();
#Override
protected Bitmap doInBackground(String... args) {
try {
downloadPath = args[0];
return BitmapFactory.decodeStream((InputStream) new URL(downloadPath).getContent());
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Bitmap bitmap) {
if (bitmap != null) {
String photoFileName = downloadPath.substring(downloadPath.lastIndexOf('/') + 1);
String saveImagePath = "";
int dotposition = photoFileName.lastIndexOf(".");
String filename_Without_Ext = photoFileName.substring(0, dotposition);
String Ext = photoFileName.substring(dotposition + 1, photoFileName.length());
String newFileName = filename_Without_Ext + "." + Ext;
saveImagePath = sdCardBasePath + "/" + newFileName;
saveBitmapToJPEGFile(MainActivity.this, bitmap, new File(saveImagePath), 900);
saveBitmapToFile(MainActivity.this, myImageViewImage, saveImagePath);
} else {
myImageViewImage.setImageResource(R.drawable.default_photo);
}
}
}
public Boolean saveBitmapToFile(Context ctx, Bitmap tempBitmap, File targetFile, int i) {
Boolean result = true;
if (tempBitmap != null) {
FileOutputStream out = null;
try {
out = new FileOutputStream(targetFile);
tempBitmap.compress(Bitmap.CompressFormat.JPEG, CommonUtils.JPEG_COMPRESION_RATIO_DEFAULT, out);
} catch (FileNotFoundException e) {
result = false;
e.printStackTrace();
}
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} else {
result = false;
}
return result;
}
public void loadImageWithGlide(Context theCtx, ImageView theImageView, String theUrl) {
Glide.with(theCtx)
.load(theUrl)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.into(theImageView);
}
I couldn't get the code I originally posted to work even with all of you's guys help. Big thanks to anybody that posted with suggestions!!. Anyway I went back to scratch and finally got it to work with even less code!
Here's my working code
public class MainActivity extends AppCompatActivity {
EditText editText;
Bitmap bitmap;
ImageView view;
Button btn;
ProgressDialog pd;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText = (EditText) findViewById(R.id.inputFileUrl);
view = (ImageView) findViewById(R.id.imageView);
btn = (Button) findViewById(R.id.retrieveFileUrl);
}
public void buttonClicked(View view) {
String stringUrl = editText.getText().toString();
new DownloadTask().execute(stringUrl);
}
// Uses AsyncTask to create a task away from the main UI thread. This task takes
// URL string and uses it to create an HttpUrlConnection. Once the connection
// has been established, the AsyncTask downloads the contents of the webpage as
// an InputStream. Finally, the InputStream is converted into a string, which is
// displayed in the UI by the AsyncTask's onPostExecute method.
public class DownloadTask extends AsyncTask<String, Void, Bitmap> {
#Override
protected void onPreExecute() {
//Create PD, SET Properties
pd = new ProgressDialog(MainActivity.this);
pd.setTitle("Image Downloader");
pd.setMessage("Downloading....");
pd.setIndeterminate(false);
pd.show();
}
#Override
protected Bitmap doInBackground(String... urls) {
String url = urls[0];
try {
bitmap = BitmapFactory.decodeStream(new URL(url).openConnection().getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
return bitmap;
}
// onPostExecute displays the results of the AsyncTask.
#Override
protected void onPostExecute(Bitmap url) {
if (bitmap != null) {
super.onPostExecute(url);
view.setImageBitmap(url);
//Dismiss
pd.dismiss();
} else {
Toast.makeText(getApplicationContext(), "Failed to Download Image", Toast.LENGTH_LONG).show();
//Dismiss
pd.dismiss();
}
}
}
}
Use library like Glide. You can simply add Glide dependency in Gradle:
compile 'com.github.bumptech.glide:glide:3.7.0'
and you can load image simply by writing:
Glide.with(context).load("image_url").into(imagevie_name);
Related
I have a download button in my app.When I press the download button it downloads an audio file from provided url.But the problem is I want to save the file in my internal storage folder called "DownloadTestFolder",it is showing an error.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Download"
android:onClick="Download"
android:id="#+id/download"/>
</LinearLayout>
public class DownloadTest extends Activity {
DownloadManager downloadManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.download_test);
}
public void Download(View view){
downloadManager=(DownloadManager)getSystemService(Context.DOWNLOAD_SERVICE);
Uri uri=Uri.parse("My Url");
DownloadManager.Request request = new DownloadManager.Request(uri);
try{
request.setDestinationInExternalPublicDir(getFilesDir()+"/DownloadTestFolder","/");
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
Long reference = downloadManager.enqueue(request);
}catch (Exception e){
/* Error
}
}
}
The DownloadManager can only download to external storage, you need to implement your own download manager.
Use this method to save file:
// DownloadFile AsyncTask
private class DownloadFile extends AsyncTask<String, Void, Bitmap> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Bitmap doInBackground(String... URL) {
String imageURL = URL[0];
Bitmap bitmap = null;
try {
// Download Image from URL
InputStream input = new java.net.URL(URL).openStream();
// Decode Bitmap
bitmap = BitmapFactory.decodeStream(input);
} catch (Exception e) {
e.printStackTrace();
}
return bitmap;
}
#Override
protected void onPostExecute(Bitmap result) {
if (result != null) {
File dir = new File(mContext.getFilesDir(), "MyImages");
if(!dir.exists()){
dir.mkdir();
}
File destination = new File(dir, "image.jpg");
try {
destination.createNewFile();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
result.compress(Bitmap.CompressFormat.PNG, 0 /*ignored for PNG*/, bos);
byte[] bitmapdata = bos.toByteArray();
FileOutputStream fos = new FileOutputStream(destination);
fos.write(bitmapdata);
fos.flush();
fos.close();
selectedFile = destination;
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Usage:
new DownloadFile().execute("url_here");
Note: I have added code for image type file
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 6 years ago.
Hi I am learning Android App Development. For this, I wanted to make myself a simple wallpaper app. Hence, I wrote something roughly which is presented here. I want to get wallpaper urls from json. Unfortunately, I am unable to get data from my server. java.lang.NullPointerException: Attempt to read from null array
How do I get the data correctly from the jsonParse asynctask?
I am stuck on this the whole day. What could have gone wrong here?
Here is my code:
myjson.json:
{
"walls":[
{"ourUrl":"http://www.hdbloggers.net/wp-content/uploads/2016/01/Wallpapers-for-Android.jpg"},
{"ourUrl":"http://androidwallpape.rs/content/02-wallpapers/131-night-sky/wallpaper-2707591.jpg"},
{"ourUrl":"http://androidwallpape.rs/content/02-wallpapers/155-starrynight/starry-night-sky-star-galaxy-space-dark-9-wallpaper.jpg"}
]
}
MainActivity.java:
package regalstreak.me.wallpapers;
import android.app.Activity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
public class MainActivity extends Activity {
RecyclerView recyclerView;
RecyclerView.LayoutManager layoutManager;
RecyclerView.Adapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = (RecyclerView)findViewById(R.id.recycler_view);
layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
adapter = new RecyclerAdapter(this);
recyclerView.setAdapter(adapter);
}
}
RecyclerAdapter.java:
package regalstreak.me.wallpapers;
import android.content.Context;
import android.os.AsyncTask;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import org.apache.commons.io.IOUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.List;
// This is a recycleradapter which will set the correct images to the correct position in the recyclerview.
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.ViewHolder> {
private Context myCtx1;
String[] arr;
String[] arrurl;
String jsonURL = "http://dev.regalstreak.me/myjson.json";
public RecyclerAdapter(Context ctx) {
this.myCtx1 = ctx;
}
public ImageView Image;
private String[] mText = {
"Text 1",
"Text 2",
"Text 3"
};
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView Text;
public ViewHolder(View itemView) {
super(itemView);
Image = (ImageView) itemView.findViewById(R.id.image_view);
Text = (TextView) itemView.findViewById(R.id.text_view);
}
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.wallpapers_list, viewGroup, false);
ViewHolder viewHolder = new ViewHolder(v);
return viewHolder;
}
#Override
public void onBindViewHolder(ViewHolder viewHolder, int i) {
viewHolder.Text.setText(mText[i]);
new jsonParse().execute();
new DownloadImageTask(Image).execute(arrurl[i]);
}
#Override
public int getItemCount() {
return mText.length;
}
class jsonParse extends AsyncTask<String, Void, String[]> {
protected String[] doInBackground(String[] urls) {
String myText = null;
String url = urls[0];
String ourUrl;
try {
InputStream in = new java.net.URL(jsonURL).openStream();
myText = IOUtils.toString(in, "utf-8");
in.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
// Parse the json
List<String> allUrls = new ArrayList<String>();
JSONObject jsonObjectRoot = new JSONObject(myText);
JSONArray jsonArray = jsonObjectRoot.getJSONArray("walls");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
ourUrl = jsonObject.getString("ourUrl");
allUrls.add(ourUrl);
}
arr = allUrls.toArray(new String[allUrls.size()]);
} catch (JSONException e) {
e.printStackTrace();
}
return arr;
}
protected void onPostExecute(String[] result){
arrurl = result;
}
}
}
DownloadImageTask.java:
package regalstreak.me.wallpapers;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.ImageView;
import java.io.InputStream;
// Here, we will download the wallpapers obtained from jsonData with an asynctask.
public class DownloadImageTask extends AsyncTask<String, Void, Bitmap>{
ImageView bmImage;
public DownloadImageTask(ImageView bmImage){
this.bmImage = bmImage;
}
protected Bitmap doInBackground(String... urls) {
String urldisplay = urls[0];
Bitmap mIcon11 = null;
try {
InputStream in = new java.net.URL(urldisplay).openStream();
mIcon11 = BitmapFactory.decodeStream(in);
in.close();
} catch (Exception e) {
Log.e("Error getting images.", e.getMessage());
e.printStackTrace();
}
return mIcon11;
}
protected void onPostExecute(Bitmap result){
bmImage.setImageBitmap(result);
}
}
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="regalstreak.me.wallpapers.MainActivity">
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/recycler_view" />
</RelativeLayout>
wallpaper_list.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/relative"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="5dp">
<ImageView
android:id="#+id/image_view"
android:layout_width="match_parent"
android:layout_height="150dp" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignBottom="#id/image_view"
android:alpha="0.6"
android:background="#color/colorDivider"
android:padding="9dp">
<TextView
android:id="#+id/text_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAlignment="center"
android:textColor="#color/colorPrimaryText" />
</RelativeLayout>
</RelativeLayout>
I have used HttpURLConnection class here for quick response and features like cache. The data received from the URL is being added to an input stream which we then convert to a String builder to get a string object which we can further use with the JSON classes.
PS - Add the AsyncTask code to your MainActivity itself, don't make a separate java file for this.
Tip - Always verify the json using this tool - jsonlint.com
MainActivity
/*
your code
*/
#Override
protected void onCreate(Bundle savedInstanceState) {
new MyAsyncTask().execute("");
}
class MyAsyncTask extends AsyncTask<String, String, Void> {
private ProgressDialog progressDialog = new ProgressDialog(StartScreen.this);
InputStream inputStream = null;
String result = "";
ArrayList<String> list;
protected void onPreExecute() {
progressDialog.setTitle("Downloading JSON Data");
progressDialog.show();
// above code makes a dialog with a progress bar
}
#Override
protected Void doInBackground(String... params) {
ArrayList<String> param = new ArrayList<String>();
URL url, url2;
try{
url = new URL("http://dev.regalstreak.me/myjson.json");
// link to your json file
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setUseCaches(false);
inputStream = new BufferedInputStream(urlConnection.getInputStream());
}catch (MalformedURLException malle){
Log.e("Mal", ""+malle);
malle.printStackTrace();
}catch (IOException ioe){
Log.e("IO", ""+ioe);
ioe.printStackTrace();
}
// Convert response to string using String Builder
try {
BufferedReader bReader = new BufferedReader(new InputStreamReader(inputStream, "utf-8"), 8);
StringBuilder sBuilder = new StringBuilder();
String line = null;
while ((line = bReader.readLine()) != null) {
sBuilder.append(line + "\n");
}
inputStream.close();
result = sBuilder.toString();
} catch (Exception e) {
Log.e("StringBuilding", "Error converting result " + e.toString());
}
return null;
}
protected void onPostExecute(Void v) {
//parse JSON data
try {
JSONObject jobj = new JSONObject(result);
//Taking a JSON Array from the JSONObject created above
String url = jobj.getString("ourUrl");
// We are adding this string to the ArrayList
list.add(url);
progressDialog.dismiss();
Context con = ListLoader.this.getApplication();
adapter = new RecyclerAdapter(list,con);
recyclerView.setAdapter(adapter);
} catch (JSONException e) {
Log.e("JSONException", "Error: " + e.toString());
} // catch (JSONException e)
}
}
/*
your code
*/
Now to display the images more effectively in the list, use the repo Universal image loader. It has a lot of features. You can get it here - https://github.com/nostra13/Android-Universal-Image-Loader
And then add this kind of code to display the images. Put it inside the onBindViewHolder
Adapter
#Override
public void onBindViewHolder(DataHolder holder, int position) {
ImageLoaderConfiguration config;
config = new ImageLoaderConfiguration.Builder(mContext).build();
ImageLoader.getInstance().init(config);
imageLoader = ImageLoader.getInstance();
DisplayImageOptions options = new DisplayImageOptions.Builder()
.showImageForEmptyUri(R.drawable.ic_error_black_48dp) // displays this image not found
.showImageOnFail(R.drawable.ic_error_black_48dp) // Displays this on failure
.showImageOnLoading(R.drawable.white) // Displays while loading
.cacheInMemory(false)
.cacheOnDisk(true)
.build();
imageLoader.displayImage(list.get(position), holder.imageView, options);
// We are feeding the urls here.
}
I'm using Google places API and it is returning all the places in my location. However I only want it to return a type for "car-repair" I think I nearly have it but I'm missing something if anyone could guide me in the right direction it would be great :)
My Code so far
PlacPickerActivity
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.Html;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import com.google.android.gms.common.GooglePlayServicesNotAvailableException;
import com.google.android.gms.common.GooglePlayServicesRepairableException;
import com.google.android.gms.location.places.Place;
import com.google.android.gms.location.places.ui.PlacePicker;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.LatLngBounds;
public class PlacePickerActivity extends AppCompatActivity {
private static final int PLACE_PICKER_REQUEST = 1;
String url="https://maps.googleapis.com/maps/api/place/textsearch/json?type=car_repair&key=AIzaSyBKsTtLyMBQH8mhvbknJ4MvZwACotmeYO0";
private TextView mName;
private TextView mAddress;
private TextView mAttributions;
private TextView mNumber;
private static final LatLngBounds Sligo = new LatLngBounds(
new LatLng(54.27, -8.47), new LatLng(54.27, -8.47));
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_place_picker);
mName = (TextView) findViewById(R.id.textView);
mAddress = (TextView) findViewById(R.id.textView2);
mAttributions = (TextView) findViewById(R.id.textView3);
mNumber = (TextView) findViewById(R.id.textView4);
Button pickerButton = (Button) findViewById(R.id.pickerButton);
pickerButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
PlacePicker.IntentBuilder intentBuilder =
new PlacePicker.IntentBuilder();
intentBuilder.setLatLngBounds(Sligo);
Intent intent = intentBuilder.build(PlacePickerActivity.this);
startActivityForResult(intent, PLACE_PICKER_REQUEST);
} catch (GooglePlayServicesRepairableException
| GooglePlayServicesNotAvailableException e) {
e.printStackTrace();
}
}
});
}
#Override
protected void onActivityResult(int requestCode,
int resultCode, Intent data) {
if (requestCode == PLACE_PICKER_REQUEST
&& resultCode == Activity.RESULT_OK) {
final Place place = PlacePicker.getPlace(this, data);
final CharSequence name = place.getName();
final CharSequence address = place.getAddress();
final CharSequence formatted_phone_number = place.getPhoneNumber();
String attributions = (String) place.getAttributions();
if (attributions == null) {
attributions = "";
}
mName.setText(name);
mAddress.setText(address);
mAttributions.setText(Html.fromHtml(attributions));
mNumber.setText(formatted_phone_number);
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
}
Manifest File
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.truiton.placepicker">
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme">
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version"/>
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="AIzaSyBKsTtLyMBQH8mhvbknJ4MvZwACotmeYO0"/>
<activity
android:name=".PlacePickerActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
When I type in the URL into my browser on my PC it returns all the type "car_repair" in my area therefore my API Key does work
Try with a query similar to this:
Location is in format latitude,longitude...and be careful is "types" not type.
https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=54.27,-8.47&radius=1000&types=car_repair&key=AddYourOwnKeyHere
Because this API return the place type inside a scope. There is a method may improve the result but still not optimal, which is called setLatLngBounds.The link is https://developers.google.com/android/reference/com/google/android/gms/location/places/ui/PlacePicker.IntentBuilder#public-method-summary
I have tried this API before and find it is totally a mess in some degree.
For example, if you want to find restaurant inside a university, this API will not only return you the restaurant but also many other types like University. Setting a bound maybe be good but still get annoying result if you only use the API.
If you just want the type of car-repair, I suggest you write a filter to filter other types and only keep car-repair type and relevant information.
I've prepared this for you , hope it helps
// A class to store your results
public class Place {
private String icon;
private Double latitude;
public void setIcon(String icon) {
this.icon=icon;
}
public void setLatitude(Double latitude) {
this.latitude=latitude;
}
// .....
}
// Utility class to keep things simple
public class Functions {
public static JSONObject convertInputStreamToJSONObject(InputStream inputStream)
throws JSONException, IOException
{
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String line = "";
String result = "";
while ((line = bufferedReader.readLine()) != null)
result += line;
inputStream.close();
return new JSONObject(result);
}
public static ArrayList<Place> parsePlacesFromJson(JSONObject datos) throws JSONException {
List<Place> placesList = new ArrayList<>();
// in your case this must be "results" I think
final int LIST_LENGTH = datos.getJSONArray("results").length();
//final int LIST_LENGTH = datos.getJSONArray("nameOfTheJsonMainArray").length();
Log.d("Length", String.valueOf(LIST_LENGTH));
// For every element in the list
for(int i = 0; i < LIST_LENGTH; i++) {
// Instance of a new Place
Place place = new Place();
// Get data as needed, this represents one place
JSONObject obj = datos.getJSONArray("results").getJSONObject(i);
Double latitude = obj.getJSONObject("geometry").getJSONObject("location").getDouble("lat");
String icon = obj.getString("icon");
place.setLatitude(latitude);
place.setIcon(icon);
//....
placesList.add(place)
}
return placesList;
}
}
// The google places reader class
public class ApiReader {
private static final String TAG = "API_READER";
Context context;
View v;
public ApiReader(Context context, View v) {
this.context = context;
this.v = v;
}
private static final String APIKEY = "yourkeyhere";
private static String ENDPOINT =
"https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=54.27,-8.47&radius=1000&types=car_repair&key=%s";
// Method to be called
public void getCarRepairs() throws IOException {
URL url = new URL(String.format(ENDPOINT, APIKEY));
new GetPlaces().execute(url);
}
// Inner asyctask class
private class GetPlaces extends AsyncTask<URL, Integer, List<Place>> {
List<Place> lista;
#Override
protected List<Place> doInBackground(URL... params) {
JSONObject datos;
URL url = params[0];
HttpURLConnection urlConnection = null;
try {
urlConnection = (HttpURLConnection) url.openConnection();
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
datos = Functions.convertInputStreamToJSONObject(in);
Log.i(TAG, datos.toString());
// De los datos obtenemos un objeto Place
lista = Functions.parsePlacesFromJson(datos);
Log.i(TAG, "" + lista.toString());
Log.i(TAG, "Went into try was OK.");
} catch (Exception e) {
Log.e(TAG, e.toString());
Log.i(TAG, "Went into catch");
} finally {
urlConnection.disconnect();
Log.i(TAG, "Went into finally, urlConnection disconnected.");
}
return lista;
}
// This method it gets what the "doInBackGround" returns
protected void onPostExecute(List<Place> placesList) {
if(placesList != null) {
// Do whatever with the list of places
//Functions.updateView(v, placesList);
}
}
}
}
// And to make things work in yout activity just do like this
ApiReader api = new ApiReader(this, findViewById(R.id.mainLayout));
try {
api.getCarRepairs();
} catch (IOException e) {
e.printStackTrace();
}
Enjoy !!
I am trying to download image and decode it to bitmap using BitmapFactory, but decodeStream always return null. I've googled many similar questions, tried many examples, but didn't find solution.
Here is my code:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void downloadButton(View v)
{
String imageUrl = "http://www.picgifs.com/bird-graphics/bird-graphics/elf-owl/bird-graphics-elf-owl-527150.bmp";
new Thread(new ImageDownloader(imageUrl)).start();
}
public void showImageButton(View v)
{
Bitmap image = ImageHandler.getImage();
if (image == null)
Log.e("Error", "No image available");
else {
ImageView imageView = (ImageView)findViewById(R.id.ImageView);
imageView.setImageBitmap(image);
}
}
}
class ImageHandler
{
static protected List<Bitmap> imagesList;
static public void addImage(Bitmap image)
{
imagesList.add(image);
}
static public Bitmap getImage()
{
if (!imagesList.isEmpty())
return imagesList.get(0);
else
return null;
}
}
class ImageDownloader implements Runnable
{
public Bitmap bmpImage;
private String urlString;
public ImageDownloader(String urlString)
{
this.urlString = urlString;
}
public void run()
{
try
{
AndroidHttpClient client = AndroidHttpClient.newInstance("Android");
HttpGet getRequest = new HttpGet(urlString);
HttpResponse response = client.execute(getRequest);
HttpEntity entity = response.getEntity();
InputStream inputStream = null;
inputStream = (new BufferedHttpEntity(entity)).getContent();
bmpImage = BitmapFactory.decodeStream(inputStream);
//bmpImage = BitmapFactory.decodeStream(new URL(urlString).openConnection().getInputStream());
}
catch (Exception e)
{
Log.e("ImageDownloadError", e.toString());
return;
}
if (bmpImage != null)
{
ImageHandler.addImage(bmpImage);
Log.i("Info", "Image download successfully");
}
else
Log.e("Error", "Bitmap is null");
}
}
p.s showImageButton throws IllegalStateException, but I was already sick of it.
I think the problem is that once you've used an InputStream from a HttpUrlConnection, you can't rewind and use the same InputStream again. Therefore you have to create a new InputStream for the actual sampling of the image. Otherwise we have to abort the http request.
Only once we can use inputstream for httprequest, if you are trying to download another image,then it will throw an error as "InputStream already created" like this. so we need to abort the httprequest once downloaded using httpRequest.abort();
Use this:
HttpGet httpRequest = new HttpGet(URI.create(path) );
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response = (HttpResponse) httpclient.execute(httpRequest);
HttpEntity entity = response.getEntity();
BufferedHttpEntity bufHttpEntity = new BufferedHttpEntity(entity);
bmp = BitmapFactory.decodeStream(bufHttpEntity.getContent());
httpRequest.abort();
as per my view two Reasons are there
class ImageHandler is not able to get the image
android is giving problem to take gif image from source.
I am uploading a working code hope this will solve Your Problem.
MainActivity
public class MainActivity extends Activity {
private ProgressDialog progressDialog;
private ImageView imageView;
private String url = "http://www.9ori.com/store/media/images/8ab579a656.jpg";
private Bitmap bitmap = null;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = (ImageView) findViewById(R.id.imageView);
Button start = (Button) findViewById(R.id.button1);
start.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
progressDialog = ProgressDialog.show(MainActivity.this,
"", "Loading..");
new Thread() {
public void run() {
bitmap = downloadBitmap(url);
messageHandler.sendEmptyMessage(0);
}
}.start();
}
});
}
private Handler messageHandler = new Handler() {
public void handleMessage(Message msg) {
super.handleMessage(msg);
imageView.setImageBitmap(bitmap);
progressDialog.dismiss();
}
};
private Bitmap downloadBitmap(String url) {
// Initialize the default HTTP client object
final DefaultHttpClient client = new DefaultHttpClient();
//forming a HttoGet request
final HttpGet getRequest = new HttpGet(url);
try {
HttpResponse response = client.execute(getRequest);
//check 200 OK for success
final int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != HttpStatus.SC_OK) {
Log.w("ImageDownloader", "Error " + statusCode +
" while retrieving bitmap from " + url);
return null;
}
final HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream is = null;
try {
// getting contents from the stream
is = entity.getContent();
// decoding stream data back into image Bitmap
final Bitmap bitmap = BitmapFactory.decodeStream(is);
return bitmap;
} finally {
if (is != null) {
is.close();
}
entity.consumeContent();
}
}
} catch (Exception e) {
getRequest.abort();
Log.e(getString(R.string.app_name), "Error "+ e.toString());
}
return null;
}
}
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" >
<Button
android:id="#+id/button1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="15dp"
android:text="Download Image" />
<ImageView
android:id="#+id/imageView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="centerInside"
android:src="#drawable/ic_launcher" />
</LinearLayout>
and also don't forget to give INTERNET Permission in Manifest.xml file
I try to build a custom video recording app and followed a tutorial on the internet. However I get the problem that the screen goes to black after pressing the start button and nothing else happened. After pressing stop button, I checked the directory where I put the output video. It is there but the size is 0 KB.
I used a surfaceview and here is the xml layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/hello"
/>
<Button
android:id="#+id/start"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="- Start Camera Preview -"
/>
<Button
android:id="#+id/stop"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="- Stop Camera Preview -"
/>
<SurfaceView
android:id="#+id/surfaceview"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>
And here is brief code for recording video:
public class CamTestActivity extends Activity implements SurfaceHolder.Callback{
private static final String TAG = "Camera-Tutorial";
private SurfaceView surfaceView;
private SurfaceHolder surfaceHolder;
private Camera camera;
private boolean previewRunning;
private int VIDEO_TYPE = 3;
private int intVideoIndex = 1;
private MediaRecorder mediaRecorder;
private final int maxDurationInMs = 20000;
private final int videoFramesPerSecond = 20;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.videopreview);
// setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
surfaceView = (SurfaceView) findViewById(R.id.surfaceview);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
Button start_video = (Button) findViewById(R.id.start);
Button stop_video = (Button) findViewById(R.id.stop);
stop_video.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
mediaRecorder.stop();
camera.lock();
}
});
start_video.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
try {
camera.unlock();
mediaRecorder = new MediaRecorder();
mediaRecorder.setCamera(camera);
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mediaRecorder.setOutputFile(GetOutputMediaFileDir(VIDEO_TYPE,intVideoIndex));
mediaRecorder.setVideoFrameRate(1);
mediaRecorder.setVideoEncoder(MediaRecorder.AudioEncoder.AAC);
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
mediaRecorder.prepare();
mediaRecorder.start();
} catch (IllegalStateException e) {
Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG).show();
// Log.e(TAG,e.getMessage());
// e.printStackTrace();
} catch (IOException e) {
Log.e(TAG,e.getMessage());
// e.printStackTrace();
}
}
});
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
camera = Camera.open();
if (camera != null){
Camera.Parameters params = camera.getParameters();
camera.setParameters(params);
}
else {
Toast.makeText(getApplicationContext(), "Camera not available!", Toast.LENGTH_LONG).show();
finish();
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
if (previewRunning){
camera.stopPreview();
}
Camera.Parameters p = camera.getParameters();
p.setPreviewSize(width, height);
camera.setParameters(p);
try {
camera.setPreviewDisplay(holder);
camera.startPreview();
previewRunning = true;
}
catch (IOException e) {
Log.e(TAG,e.getMessage());
e.printStackTrace();
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
camera.stopPreview();
previewRunning = false;
camera.release();
}
public static String GetOutputMediaFileDir(int fileType, int index){
String fileDir=null;
String strIndex = Integer.toString(index);
if(fileType == 1)
{
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_MUSIC), "Audio");
if (! mediaStorageDir.exists()){
if (! mediaStorageDir.mkdirs()){
return null;
}
}
fileDir = mediaStorageDir.getPath() + File.separator +
"AUDIO_"+ strIndex + ".mp4";
}
if(fileType == 2)
{
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "Image");
if (! mediaStorageDir.exists()){
if (! mediaStorageDir.mkdirs()){
return null;
}
}
fileDir = mediaStorageDir.getPath() + File.separator +
"IMAGE_"+ strIndex + ".jpeg";
}
if(fileType == 3)
{
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_MOVIES), "Video");
if (! mediaStorageDir.exists()){
if (! mediaStorageDir.mkdirs()){
return null;
}
}
fileDir = mediaStorageDir.getPath() + File.separator +
"VIDEO_"+ strIndex + ".mp4";
}
return fileDir;
}
}
Any ideas of how to solve the problem? Thanks a lot in advance.
Changes that solve the problem:
Firstly I set the video encoder to an audio encoder, this should be changed;
Secondly mediaRecorder.setPreviewDisplay(surfaceView.getHolder().getSurface()); should be added beforemediaRecorder.prepare()
Then it works properly.
I experienced this issue on an HTC Incredible device, yet it worked perfectly on the 8 others I tested it on. Here is the post the 'solved' that issue:
https://stackoverflow.com/a/9903357/1426565
I narrowed the actual fix down to a specific line:
recorder.setVideoSize(width, height);
The framerate/bitrate settings were irrelevant in the fix, and I'm unsure if using the DEFAULTs for sources, output format, and encoders will change anything, but if you think about it, it shouldn't affect it at all.
These are the other settings I'm using with it (make sure size is set before any Encoder):
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
recorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
recorder.setPReviewDisplay(surfaceView.getHolder().getSurface())
Also note, in testing yesterday on ICS we encountered an issue where setFrameRate was not supported, as well as setVideoSize was not supported. So, in the fix I'm about to attempt, I'm just going to surround the setVideoSize with a try/catch block, remove setFrameRate, and hope to God that fixes it. If not, I'll probably have to have to just exclude it on certain devices.