I'm writing Espresso tests to run on my React Native app. I'm using Espresso-Intents to simulate the user taking a picture, with the following code:
public void takePicture() {
Instrumentation.ActivityResult result = createImageCaptureActivityResultStub();
intending(hasAction(MediaStore.ACTION_IMAGE_CAPTURE)).respondWith(result);
clickText("Camera");
}
public static Bitmap getBitmapFromURL(String src) {
try {
URL url = new URL(src);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
Bitmap myBitmap = BitmapFactory.decodeStream(input);
return myBitmap;
} catch (IOException e) {
// Log exception
System.out.println(e.toString());
return null;
}
}
private Instrumentation.ActivityResult createImageCaptureActivityResultStub() {
// Put the drawable in a bundle.
Bundle bundle = new Bundle();
bundle.putParcelable("data", getBitmapFromURL("https://vignette.wikia.nocookie.net/the-feed-your-pets-community/images/6/69/Banana.png/revision/latest?cb=20180527162222"));
// Create the Intent that will include the bundle.
Intent resultData = new Intent();
resultData.putExtras(bundle);
// Create the ActivityResult with the Intent.
return new Instrumentation.ActivityResult(Activity.RESULT_OK, resultData);
}
When running, the camera intent is successfully stubbed, but the view which should display the photo is stuck in its loading state.
In debugging, I have discovered that getBitmapFromURL is not the problem, because bundle contains the correct image.
Could anyone suggest where the problem may lie, or how best to debug further?
Related
I have coded an update dialog in my app which checks a json file on my server to see if an update is available and then shows an update app dialog box. I know that I can send users to playstore by using Intent but I saw facebook and some other apps also show the same dialog with update button and upon pressing that button, the app starts downloading and installing instantly without going to playstore. However when I added a download AsyncTask to download and install my app, it shows parse error.
Here is my code to download and parse:
public class DownloadTask extends AsyncTask<String, Integer, String> {
#Override
protected String doInBackground(String... urls) {
String path = "/sdcard/MyApp.apk";
try {
URL url = new URL(urls[0]);
URLConnection connection = url.openConnection();
connection.connect();
int fileLength = connection.getContentLength();
// download the file
InputStream input = new BufferedInputStream(url.openStream());
OutputStream output = new FileOutputStream(path);
byte data[] = new byte[1024];
long total = 0;
int count;
while ((count = input.read(data)) != -1) {
total += count;
publishProgress((int) (total * 100 / fileLength));
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
} catch (Exception e) {
}
return path;
}
// begin the installation by opening the resulting file
#Override
protected void onPostExecute(String path) {
Intent i = new Intent();
i.setAction(Intent.ACTION_VIEW);
i.setDataAndType(Uri.fromFile(new File(path)), "application/vnd.android.package-archive" );
Log.d("Lofting", "About to install new .apk");
getContext().startActivity(i);
}
}
Can someone please tell me what am I doing wrong here?
Thanks in advance. :)
So I basically have a List of URIs, each has a .jpeg file, and I want to show this list like a GIF file (not necessesary to make a gif, only to display).
So after a research I found the AnimationDrawble object, converted each URI into Drawable and added it as a frame to AnimationDrawable.
This is my code:
AnimationDrawable ad = new AnimationDrawable();
Drawable[] dr = new Drawable[position+1];
ProgressItem pi;
try {
for (int i = 0; i <= position; i++) {
pi = progress.get(i);
try {
dr[i] = drawableFromUrl(pi.getImage());
} catch (IOException ios) {
Toast.makeText(activity, ios.getMessage(), Toast.LENGTH_SHORT).show();
}
}
}
catch(Exception ex)
{
Toast.makeText(activity, ex.getMessage(), Toast.LENGTH_SHORT).show();
}
Intent i = new Intent(activity,ProgressImage.class);
DataWraper.setItems(dr);
drawableFromUrl:
public Drawable drawableFromUrl(String url) throws IOException {
Bitmap x;
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
MyDownloadTask mdt = new MyDownloadTask();
try{
mdt.execute(connection);
}
catch(Exception ex)
{
Toast.makeText(activity, ex.getMessage(), Toast.LENGTH_SHORT).show();
}
InputStream input = mdt.getInputStream();
x = BitmapFactory.decodeStream(input);
return new BitmapDrawable(x);
}
The implementation part:
Glide.with(this)
.load(ad)
.into(progressImage);
When I'm trying to Glide the AnimationDrawble into the ImageView I get the following exception:
java.lang.IllegalArgumentException: Unknown type class android.graphics.drawable.AnimationDrawable.
This made me hesistate the way I'm trying to pull this off. Should this be this complicated?
If this is the right way, what am I doing wrong? maybe there's another way of doing so? I'd love to get some details. Thanks in advance!
https://github.com/koral--/android-gif-drawable
Not sure if you're open to any 3rd party libraries, but i used this one for gifs before and it worked quite well for me
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
What is the best way to load a notification image?
Here's my current way: As you can see the image loads synchronously and thus the notification can be delayed. This is a bad way.
public Bitmap getBitmapFromURL(String strURL) {
try {
URL url = new URL(strURL);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
Bitmap myBitmap = BitmapFactory.decodeStream(input);
return myBitmap;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
Bitmap bitmap = getBitmapFromURL("https://graph.facebook.com/YOUR_USER_ID/picture?type=large");
// CONSTRUCT THE NOTIFICATION DETAILS
builder.setAutoCancel(true);
builder.setSmallIcon(R.drawable.ic_launcher);
builder.setContentTitle("Some Title");
builder.setContentText("Some Content Text");
builder.setLargeIcon(bitmap);
builder.setContentIntent(pendingIntent);
I really need an answer to continue working on my project.
You should first notify your Notification with no image or place holder, then load your bitmap with an AsyncTask, or use Picasso and Target callback.
Give to your task the builder that you used for the first notify, when bitmap is loaded, add it to the builder, and then re-notify your Notification.
If there's a risk that content had changed before complete image loading, store a variable that identify your current content to show, that you can check before renotify.
You can follow that exemple of MediaNotificationManager provide by google UniversalMusicPlayer project.
In your case :
// CONSTRUCT THE NOTIFICATION DETAILS
builder.setAutoCancel(true);
builder.setSmallIcon(R.drawable.ic_launcher);
builder.setContentTitle("Some Title");
builder.setContentText("Some Content Text");
//builder.setLargeIcon(bitmap); // replace this line with place holder drawable from resources
builder.setContentIntent(pendingIntent);
manager.notify(NOTIFICATION_ID, builder.build());
currentLoadImageTask = new LoadImageTask(manager, builder);
currentLoadImageTask.execute("https://graph.facebook.com/YOUR_USER_ID/picture?type=large");
// ...
static class LoadImageTask extends AsyncTask<String, Void, Bitmap> {
final NotificationManager manager;
final NotificationCompat.Builder builder;
public LoadImageTask(final NotificationManager manager, final NotificationCompat.Builder builder) {
this.manager = manager;
this.builder = builder;
}
#Override
protected Bitmap doInBackground(final String... strings) {
if (strings == null || strings.length == 0) {
return null;
}
try {
final URL url = new URL(strings[0]);
final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
final InputStream input = connection.getInputStream();
return BitmapFactory.decodeStream(input);
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
#Override
protected void onPostExecute(final Bitmap bitmap) {
if (bitmap == null || manager == null || builder == null) {
return;
}
builder.setLargeIcon(bitmap);
manager.notify(NOTIFICATION_ID, builder.build());
}
}
With picasso :
// CONSTRUCT THE NOTIFICATION DETAILS
builder.setAutoCancel(true);
builder.setSmallIcon(R.drawable.ic_launcher);
builder.setContentTitle("Some Title");
builder.setContentText("Some Content Text");
//builder.setLargeIcon(bitmap); // replace this line with place holder drawable from resources
builder.setContentIntent(pendingIntent);
manager.notify(NOTIFICATION_ID, builder.build());
// ...
Picasso.with(context)
.load("https://graph.facebook.com/YOUR_USER_ID/picture?type=large")
.resize(250, 250)
.into(new Target() {
#Override
public void onBitmapLoaded(final Bitmap bitmap, final Picasso.LoadedFrom from) {
builder.setLargeIcon(bitmap);
manager.notify(NOTIFICATION_ID, builder.build());
}
#Override
public void onBitmapFailed(final Drawable errorDrawable) {
// Do nothing
}
#Override
public void onPrepareLoad(final Drawable placeHolderDrawable) {
// Do nothing
}
});
If not in UiThread you can create a Runnable and execute it in Looper
final Handler uiHandler = new Handler(Looper.getMainLooper());
uiHandler.post(new Runnable() {
#Override
public void run() {
// Call from here
}
});
Picasso is much better simply because using cache.
And I highly recommend you to resize every bitmap you set in notification because it can easily provoc OutOfMemoryException if you dont.
Remember,if you are loading something using the web, you have to wait a bit.
There are several solutions:
Load an image from the web like in your example and show.
Show a stub image and show downloaded image later by updating the notification
Use a little that helps top cache web inches. For instance, picaso
http://square.github.io/picasso/
use Picasso lib to load image from url like
Picasso.with(this.load(imageUri).into(imageview_id);
I'm trying to include image sharing in my application and everything is working but the share chooser takes long time to appear on devices
here is what i'm doing:
I have ImageView "items_details_image" and I want to share its image to be able to send it through whatsapp and other apps
void ShareImg() {
try {
Uri bmpUri = getLocalBitmapUri(items_details_image);
if (bmpUri != null) {
// Construct a ShareIntent with link to image
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_STREAM, bmpUri);
shareIntent.setType("image/*");
// Launch sharing dialog for image
startActivity(Intent.createChooser(shareIntent, "Share Image"));
} else {
// ...sharing failed, handle error
}
} catch (Exception e) {
}
}
here is how I get bitmap from Image URL
public Uri getLocalBitmapUri(ImageView imageView) {
// Extract Bitmap from ImageView drawable
Drawable drawable = imageView.getDrawable();
Bitmap bmp = null;
if (drawable instanceof BitmapDrawable){
bmp = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
} else {
return null;
}
// Store image to default external storage directory
Uri bmpUri = null;
try {
File file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DOWNLOADS), "share_image_" + System.currentTimeMillis() + ".png");
file.getParentFile().mkdirs();
FileOutputStream out = new FileOutputStream(file);
bmp.compress(Bitmap.CompressFormat.PNG, 90, out);
out.close();
bmpUri = Uri.fromFile(file);
} catch (IOException e) {
e.printStackTrace();
}
return bmpUri;
}
I don't know why it is taking longer than usual comparing it with other apps on the same device such as gallery or whatever
You are doing disk I/O on the main application thread, in getLocalBitmapUri(). This will freeze your UI as long as it takes to write your bitmap to disk.
I'm building an android app that can get images from the photos gallery.
two questions if I may:
1)
Intent intent = getIntent();
Bundle extras = intent.getExtras();
String action = intent.getAction();
Uri uri = null;
// if this is from the share menu
if (Intent.ACTION_SEND.equals(action)) {
if (extras.containsKey(Intent.EXTRA_STREAM))
{
try
{
// Get resource path from intent callee
uri = (Uri) extras.getParcelable(Intent.EXTRA_STREAM);
I have this uri:
content://media/external/images/media/27031
but my code fails here with no information (it just crashes), no log cat, not console error.
try {
if (uri !=null)
{
Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uri);
imageView.setImageBitmap(bitmap);
}
} catch (IOException e) {
e.printStackTrace();
Log.e(this.getClass().getName(), e.toString());
}
how can I solve this?
(it works for this url: Uri uri = Uri.parse("content://media/external/images/media/22719");
2) i plan to save all uri's in a data structure. That's the recommended way?
or is it better to keep the photos in a local app folder?
Update
I think the problem was that the failing image was on the external SD whereas the succeeding one was on a local SD.
How can i enable getting image from the external SD ?
some code for getting a bitmap from a 'share' action on a photo...
Object obj = null;
if (Intent.ACTION_SEND.equals(_action) && _type != null) {
obj = _bundle.get("android.intent.extra.STREAM");
if( getIntent().getType().startsWith("image/") && obj != null){
if (obj instanceof android.net.Uri){ get((Uri)obj);}}
get(Uri uri){
Bitmap _bit = BitmapFactory.decodeStream(
getContentResolver().openInputStream(uri),null,options);
}