Importing multiple images in Android application - android

How can I import multiple images on my Android app? Can I assign single id to that bundle of images to bring it from drawable? Suggest me a way.
Currently I am only able to display one image multiple times in line layout. Here is the code line to bring the image:
placeholder = BitmapFactory.decodeResource(getResources(), R.drawable.picture2);
Should I enter multiple lines for picture3,picture4,...etc?

Simplest way I can think of:
int ids[] = new int[] {
R.drawable.picture2,
R.drawable.picture3,
R.drawable.picture4
};
Bitmap bitmaps[] = new Bitmap[ids.length];
for(int i = 0; i < ids.length; i += 1){
bitmaps[i] = BitmapFactory.decodeResource(getResources(), ids[i]);
}
Also you can re-write it as a function for improving modularity.
public Bitmap[] loadBitmaps(int ids[]){
Bitmap bitmaps[] = new Bitmap[ids.length];
for(int i = 0; i < ids.length; i += 1){
bitmaps[i] = BitmapFactory.decodeResource(getResources(), ids[i]);
}
return bitmaps;
}

Instead of Drawable store all images in Assets then you can get Image by passing name. Add following function in your activity.
private Bitmap getBitmapFromAsset(String paramString)
{
Object localObject = getResources().getAssets();
try
{
Bitmap ret = BitmapFactory.decodeStream(((AssetManager)localObject).open(paramString));
return ret;
}
catch (IOException ex)
{
ex.printStackTrace();
}
return null;
}

Related

Having issue on linking an image, with a bitmap created before

since a long time, I have tried to link an image to a Bitmap. I have already created the bitmap, I know how to put it into my image (here it is an icon from Google Maps but it changes nothing). What I want is link this icon to my bitmap called bmp. But there is an error :
Cannot resolve symbol 'bmp'
Here is my code to help you understand my issue :
private void initMarker(List<LocationModel> listData) {
//iterasi semua data dan tampilkan markerny
for (int i = 0; i < mListMarker.size(); i++) {
Bitmap bmp = null;
URL url;
try {
url = new URL(mListMarker.get(i).getIconImage());
bmp = BitmapFactory.decodeStream(url.openConnection().getInputStream());
} catch (IOException y) {
y.printStackTrace();
return ;
}
//set latlng nya
LatLng location = new LatLng(Double.parseDouble(mListMarker.get(i).getLatutide()), Double.parseDouble(mListMarker.get(i).getLongitude()));
//tambahkan markernya
mMap.addMarker(new MarkerOptions().position(location).title(mListMarker.get(i).getImageLocationName()).snippet(mListMarker.get(i).getIconImage()).icon(BitmapDescriptorFactory.fromBitmap(bmp)));
//.icon(BitmapDescriptorFactory.fromBitmap(XXX))
//set latlng index ke 0
LatLng latLng = new LatLng(Double.parseDouble(mListMarker.get(0).getLatutide()), Double.parseDouble(mListMarker.get(0).getLongitude()));
//lalu arahkan zooming ke marker index ke 0
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(latLng.latitude, latLng.longitude), 11.0f));
}
}
You create the instance inside the try-catch statement, but reference it outside:
try{
Bitmap bmp = ...
}catch(IOException e){
//e.print....
}
//do something with bmp
You can't do that as it's locally created within the try-catch statement and can't be accessed outside. Do this instead:
Bitmap bmp = null;
try{
URL url = new URL(mListMarker.get(i).getImageLocationName());
bmp = BitmapFactory.decodeStream(url.openConnection().getInputStream());
}catch(IOException e){
//Print stacktrace and return. Otherwise you get an NPE if it fails
}
Declaring it outside the try-catch allows it to be accessed outside it

A lot of GC_FOR_ALLOC and sometimes the transfer stops when this warning is like infinite

Ivam facing this problem of memory and it drives me crazy.
My app is receiving binary data from raspberry. With this data Im creating an int array, colors than using it to create my bitmap and display the image. The protocol of transfer is UDP.
No problem when I receive one image, but when I ask my raspberry to send 10 images for example, this message GC_FOR_ALLOC appears and sometimes the transfer stops without sending all images.
I googled this problem, I added Runtime.getRuntime().gc(); System.gc(); to my code and same problem.
I declared all my objects out of the loop to avoid creating each time a new variable, to create my bitmap Im using createBitmap(int[] colors, int width, int height, Bitmap.Config config), I read on the internet that it is not good to do this method and use instead createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter).
The problem I do not know how to use my array colors with createScaledBitmap method.
Also, I tried bitmap.recycle at the end of my loop, it sends the first image then I have an error, "trying to use a recycled".
Please can someone help me.
I can add my code if you want.
Thank you
This is the code:
class UDPServer {
MainActivity act;
final String capitalizedSentence = "well received!";
final byte[] sendData = capitalizedSentence.getBytes();
public UDPServer(MainActivity act) {
this.act=act;
}
public void connect() throws Exception {
final ImageView image = (ImageView) act.findViewById(R.id.imageDisplay);
final byte[] receiveData1=new byte[40960], receiveData2=new byte[40960], receiveData3=new byte[40960], receiveData4=new byte[40960];
final DatagramSocket serverSocket=new DatagramSocket(8080);
final DatagramPacket receivePacket1 = new DatagramPacket(receiveData1, receiveData1.length);
final DatagramPacket receivePacket2 = new DatagramPacket(receiveData2, receiveData2.length);
final DatagramPacket receivePacket3 = new DatagramPacket(receiveData3, receiveData3.length);
final DatagramPacket receivePacket4 = new DatagramPacket(receiveData4, receiveData4.length);
final Thread udpserver = new Thread()
{
public void run () {
try {
while (!isInterrupted()) {
System.out.println("waiting for the conx");
serverSocket.receive(receivePacket1);
serverSocket.receive(receivePacket2);
serverSocket.receive(receivePacket3);
serverSocket.receive(receivePacket4);
System.out.println("thank you sir");
final Bitmap bitmap=Bitmap.createBitmap(act.afficheImage(
receivePacket1.getData(),
receivePacket2.getData(),
receivePacket3.getData(),
receivePacket4.getData()),
320, 256, Bitmap.Config.ARGB_8888);
act.runOnUiThread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
image.setImageBitmap(bitmap);
}
});
InetAddress IPAddress = receivePacket1.getAddress();
int port = receivePacket1.getPort();
System.out.println("From: " + IPAddress + ":" + port);
DatagramPacket sendPacket1 = new DatagramPacket(sendData, sendData.length, IPAddress, port);
serverSocket.send(sendPacket1);
Runtime.getRuntime().gc();
System.gc();
}
serverSocket.close();
} catch (SocketException ex) {
System.out.println("UDP Port 8080 is occupied.");
} catch (IOException ex1) {
System.out.println("Error: " + ex1.getMessage());
ex1.printStackTrace();
}
}
};
udpserver.start();
}
}
this is the method afficheImage:
private static final int WIDTH = 320;
private static final int HEIGHT = 256;
public static int a=255<<24;
public static ByteBuffer buffer1;
public static short[] array=new short[WIDTH * HEIGHT];
public static byte[] si=new byte[2];
public static int[] colors = new int[WIDTH * HEIGHT];
public static int[] afficheImage(byte[] s1, byte[] s2, byte[] s3, byte[] s4){
try{
for (int i=0;i<HEIGHT*WIDTH/4;i++){
si[0] = s1[2*i];
si[1] = s1[2*i+1];
buffer1 = ByteBuffer.wrap(si);
buffer1.order(ByteOrder.LITTLE_ENDIAN);
array[i]=buffer1.getShort();
}
for (int i=0;i<HEIGHT*WIDTH/4;i++){
si[0] = s2[2*i];
si[1] = s2[2*i+1];
buffer1 = ByteBuffer.wrap(si);
buffer1.order(ByteOrder.LITTLE_ENDIAN);
array[i+s1.length/2]=buffer1.getShort();
}
for (int i=0;i<HEIGHT*WIDTH/4;i++){
si[0] = s3[2*i];
si[1] = s3[2*i+1];
buffer1 = ByteBuffer.wrap(si);
buffer1.order(ByteOrder.LITTLE_ENDIAN);
array[i+s1.length]=buffer1.getShort();
}
for (int i=0;i<HEIGHT*WIDTH/4;i++){
si[0] = s4[2*i];
si[1] = s4[2*i+1];
buffer1 = ByteBuffer.wrap(si);
buffer1.order(ByteOrder.LITTLE_ENDIAN);
array[i+3*s1.length/2]=buffer1.getShort();
}
int delta=foundMax(array)-foundMin(array);
int min=foundMin(array);
int r;
for (int i=0;i<HEIGHT*WIDTH;i++) {
r = (array[i] - min) * 255/delta;
colors[i] = a | (r << 16) | (r << 8) | r;
}
} catch (Exception ex) {
ex.printStackTrace();
}
return colors;
}
EDIT: Okay, here's the real answer:
You need to use OpenGL.
OpenGL would be a lot faster and maybe actually make your app look like a video, which is what you want.
The great thing for your use case is that OpenGL renders in a background thread, so you can build your pixel buffer from network data and render it all in the same thread.
The code is actually creating a new Bitmap with every "frame", so you should also allocate one static bitmap as well.
At the start of the connect method where you allocate the DatagramPackets, you should allocate your Bitmap too:
final Bitmap bitmap = Bitmap.createBitmap(320, 256, Bitmap.Config.ARGB_8888);
Then inside your loop after you get all your data:
int[] pixels = act.afficheImage(
receivePacket1.getData(),
receivePacket2.getData(),
receivePacket3.getData(),
receivePacket4.getData());
bitmap.setPixels(pixels, 0, 320, 0, 0, 320, 256);
You might also need some synchronization on the bitmap between the server thread that is pushing buffer data into it and the UI thread that is trying to render it into the ImageView.
Is there any way you can throttle the data coming from the Raspberry? It's possible that your Android device might be getting overwhelmed trying to handle the network data and display the image at the same time.
I can also see a bunch of other optimizations for eliminating most of those temporary work buffers, but those wouldn't really move the needle when it comes to getting rid of the OOM exceptions.

Libgdx getting Image from facebook at runtime

I have image-url getting from facebook, I want to display that image at runtine in my game in libgdx.I am using facebook graph api and parse data with help of Json parsing. my approach is as follows:
In main activity
protected void gettingfacebookData() {
try {
JSONArray friendArray = new JSONArray(
prefLevel.getFriendFacebookData());
for (int i = 0; i < friendArray.length(); i++) {
JSONObject jsonObject = friendArray.getJSONObject(i);
String name = jsonObject.getString("name");
String score = jsonObject.getString("score");
String fid = jsonObject.getString("fid");
String image = "http://graph.facebook.com/" + fid
+ "/picture?type=large";
//saving score into array list
PlayingScreen.scoreAl.add(score);
//saving image url into arraylist
PlayingScreen.imageUrlAl.add(image);
} }
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Now how can I display image at run time with this particular image url?
We use a wrapper class, that wraps Texture, for displaying images from web (like facebook profile pictures). This wrapper class takes url of the image and a temporary texture. Just as the wrapper is created, it starts to download image bytes in a background thread. Consumer of this wrapper class simply calls getTexture() to obtain texture and until download has finished, this method returns the temporary texture. When there are bytes available to create a texture getTexture() processes this bytes and starts to return new texture created from url.
Below is a simple version of this wrapper class. Note that, processTextureBytes is called inside getTexture method, not somewhere in background thread. It is because we have to construct texture in the thread which obtains the GLContext. You can add caching and retry mechanisms to this class.
BTW, instead of using http://graph.facebook.com/[uid]/picture url try using one of pic_ urls from FQL. You may want to check this.
public class WebTexture {
private final String url;
private Texture texture;
private volatile byte[] textureBytes;
public WebTexture(String url, Texture tempTexture) {
this.url = url;
texture = tempTexture;
downloadTextureAsync();
}
private void downloadTextureAsync() {
Utils.runInBackground(new Runnable() {
#Override
public void run() {
textureBytes = downloadTextureBytes();
}
});
}
private byte[] downloadTextureBytes() {
try {
return Utils.downloadData(url);
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
public Texture getTexture() {
if (textureBytes != null)
processTextureBytes();
return texture;
}
private void processTextureBytes() {
try {
Pixmap pixmap = new Pixmap(textureBytes, 0, textureBytes.length);
Texture gdxTexture = new Texture(pixmap);
gdxTexture.setFilter(TextureFilter.Linear, TextureFilter.Linear);
texture = gdxTexture;
} catch (Throwable t) {
t.printStackTrace();
} finally {
textureBytes = null;
}
}
}
You should download the image.
Once you have your image as a byte array, you can create a pixmap:
Pixmap pixmap = new Pixmap(imageBytes, 0, imageBytes.length);
Then you can use this pixmap to render the image. For example if are you using scene2d.ui you can set Image's drawable as follows:
image.setDrawable(new TextureRegionDrawable(new TextureRegion(new Texture(profilePicture))));
Hope this helps.

String processing very slow in new Android version(4.3)

I am trying to break a String into multiple pages. The string contains a story(hence a bit long one) and I need to load this into an ArrayList of Strings which will be displayed as various pages.
Below is the method in my code which takes in the long string and breaks it into pages and loads the ArrayList of Strings. My problem is that this works pretty fast in Android 3.2. But in my another phone which is 4.3, it loads very slow(say it takes about 10 seconds for what works in 2 seconds in 3.2 one). Below is my code. Can anyone of you please suggest any improvements here in the code which can make it work faster in the new version. Not sure why should new version process slower than the old one.
TextView contentTextView = (TextView)findViewById(R.id.textViewStory1);
String contentString;
TextPaint tp = contentTextView.getPaint();
String[] pages;
int totalPages=0;
ArrayList<String> pagesArray = new ArrayList<String>();
public void loadStory(String storyName){
//initialize variables
numCharsLine=0;
contentString = getStringFromTxtFile(storyName);
int linesInOnePage = getLinesInPage();//get how many lines will be displayed in one page
//load story into arraylist pagesArray
while (contentString != null && contentString.length() != 0)
{
totalPages ++;
int numChars = 0;
int lineCount = 0;
while ((lineCount < linesInOnePage) && (numChars < contentString.length())) {
numCharsLine = tp.breakText(contentString.substring(numChars), true, pageWidth, null);
numChars = numChars + numCharsLine;
lineCount ++;
}
// retrieve the String to be displayed in pagesArray
String toBeDisplayed = contentString.substring(0, numChars);
contentString = contentString.substring(numChars);
pagesArray.add(toBeDisplayed);
numChars = 0;
lineCount = 0;
}
//get the pagecount and reset pageNumber to current page
totalPages=pagesArray.size();
pages = new String[pagesArray.size()];
pages = pagesArray.toArray(pages);
}
Also below is the method for loading the contents of text file into the string
public String getStringFromTxtFile(String fileName) {
try {
InputStream is = getAssets().open(fileName+".txt");
int size = is.available();
byte[] buffer = new byte[size];
is.read(buffer);
is.close();
return new String(buffer);
}
catch (IOException e) {
throw new RuntimeException(e);
}
}
For now you are reading whole file to string, then split this string into lines and process it.
I would suggest you to union reading text from file and processing it line by line.
for example, using class LineNumberReader or BufferedReader:
BufferedReader bis = new BufferedReader(new FileReader("my/file/path"));
String line;
while ((line = bis.readLine()) != null) {
processLine(line); //process current line
}
therefore you don't have to do so many concat and substring actions.

Retrieving all Drawable resources from Resources object

In my Android project, I want to loop through the entire collection of Drawable resources. Normally, you can only retrieve a specific resource via its ID using something like:
InputStream is = Resources.getSystem().openRawResource(resourceId)
However, I want to get all Drawable resources where I won't know their ID's beforehand. Is there a collection I can loop through or perhaps a way to get the list of resource ID's given the resources in my project?
Or, is there a way for me in Java to extract all property values from the R.drawable static class?
Okay, this feels a bit hack-ish, but this is what I came up with via Reflection. (Note that resources is an instance of class android.content.res.Resources.)
final R.drawable drawableResources = new R.drawable();
final Class<R.drawable> c = R.drawable.class;
final Field[] fields = c.getDeclaredFields();
for (int i = 0, max = fields.length; i < max; i++) {
final int resourceId;
try {
resourceId = fields[i].getInt(drawableResources);
} catch (Exception e) {
continue;
}
/* make use of resourceId for accessing Drawables here */
}
If anyone has a better solution that makes better use of Android calls I might not be aware of, I'd definitely like to see them!
i used getResources().getIdentifier to scan through sequentially named images in my resource folders. to be on a safe side, I decided to cache image ids when activity is created first time:
private void getImagesIdentifiers() {
int resID=0;
int imgnum=1;
images = new ArrayList<Integer>();
do {
resID=getResources().getIdentifier("img_"+imgnum, "drawable", "InsertappPackageNameHere");
if (resID!=0)
images.add(resID);
imgnum++;
}
while (resID!=0);
imageMaxNumber=images.size();
}
I have taken Matt Huggins great answer and refactored it to make it more generic:
public static void loadDrawables(Class<?> clz){
final Field[] fields = clz.getDeclaredFields();
for (Field field : fields) {
final int drawableId;
try {
drawableId = field.getInt(clz);
} catch (Exception e) {
continue;
}
/* make use of drawableId for accessing Drawables here */
}
}
Usage:
loadDrawables(R.drawable.class);
You should use the Raw folder and AssetManager, but if you want to use drawables because why not, here is how...
Let's suppose we have a very long file list of JPG drawables and we want to get all the resource ids without the pain of retrieving one by one (R.drawable.pic1, R.drawable.pic2, ... etc)
//first we create an array list to hold all the resources ids
ArrayList<Integer> imageListId = new ArrayList<Integer>();
//we iterate through all the items in the drawable folder
Field[] drawables = R.drawable.class.getFields();
for (Field f : drawables) {
//if the drawable name contains "pic" in the filename...
if (f.getName().contains("image"))
imageListId.add(getResources().getIdentifier(f.getName(), "drawable", getPackageName()));
}
//now the ArrayList "imageListId" holds all ours image resource ids
for (int imgResourceId : imageListId) {
//do whatever you want here
}
Add a picture named aaaa and another named zzzz, then iterate through the following:
public static void loadDrawables() {
for(long identifier = (R.drawable.aaaa + 1);
identifier <= (R.drawable.zzzz - 1);
identifier++) {
String name = getResources().getResourceEntryName(identifier);
//name is the file name without the extension, indentifier is the resource ID
}
}
This worked for me.
If you find yourself wanting to do this you're probably misusing the resource system. Take a look at assets and AssetManager if you want to iterate over files included in your .apk.
I guess the reflection code will work but I don't understand why you need this.
Resources in Android are static once the application is installed so you can have a list of resources or an array. Something like:
<string-array name="drawables_list">
<item>drawable1</item>
<item>drawable2</item>
<item>drawable3</item>
</string-array>
And from your Activity you can get it by doing:
getResources().getStringArray(R.array.drawables_list);
Just do this:
Field[] declaredFields = (R.drawable.class).getDeclaredFields();
The OP wanted drawables and I needed layouts. This is what I came up with for layouts. The name.startsWith business lets me ignore system generated layouts, so you may need to tweak that a bit. This should work for any resource type by modifying the value of clz.
public static Map<String,Integer> loadLayouts(){
final Class<?> clz = R.layout.class;
Map<String,Integer> layouts = new HashMap<>();
final Field[] fields = clz.getDeclaredFields();
for (Field field : fields) {
String name = field.getName();
if (
!name.startsWith("abc_")
&& !name.startsWith("design_")
&& !name.startsWith("notification_")
&& !name.startsWith("select_dialog_")
&& !name.startsWith("support_")
) {
try {
layouts.put(field.getName(), field.getInt(clz));
} catch (Exception e) {
continue;
}
}
}
return layouts;
}
USE THIS MY CODE
R.drawable drawableResources = new R.drawable();
Class<R.drawable> c = R.drawable.class;
Field[] fields = c.getDeclaredFields();
for (int i = 0, max = fields.length; i < max; i++) {
final int resourceId;
try {
resourceId = fields[i].getInt(drawableResources);
// call save with param of resourceId
SaveImage(resourceId);
} catch (Exception e) {
continue;
}
}
...
public void SaveImage(int resId){
if (!CheckExternalStorage()) {
return;
}
Bitmap bmp = BitmapFactory.decodeResource(getResources(), resID);
try {
File dir = new File(path);
if (!dir.exists()) {
dir.mkdirs();
}
OutputStream fOut = null;
File file = new File(path, "image1.png");
file.createNewFile();
fOut = new FileOutputStream(file);
bmp.compress(Bitmap.CompressFormat.PNG, 100, fOut);
fOut.flush();
fOut.close();
MediaStore.Images.Media.insertImage(this.getContentResolver(), file.getAbsolutePath(), file.getName(), file.getName());
Log.i(LOGTAG, "Image Written to Exterbal Storage");
} catch (Exception e) {
Log.e("saveToExternalStorage()", e.getMessage());
}
}
To create an array of drawables in Kotlin:
val drawablesFields: Array<Field> = drawable::class.java.fields
val drawables: ArrayList<Drawable> = ArrayList()
for (field in drawablesFields) {
context?.let { ContextCompat.getDrawable(it, field.getInt(null)) }?.let {
drawables.add (
it
)
}
}

Categories

Resources