I am new to android. I am getting one issue as passing my image as binary in api using retrofit but while getting same binary string of image in response not able to convert binary string to Bitmap again. Below i am passing the binary string getting in response. Its a great help if anyone can help me.
"????\u0000\u0010JFIF\u0000\u0001\u0001\u0000\u0000H\u0000H\u0000\u0000??\u0000\u0011\b\u0002X\u0002?\u0003\u0001\"\u0000\u0002\u0011\u0001\u0003\u0011\u0001??\u0000\u001f\u0000\u0000\u0001\u0005\u0001\u0001\u0001\u0001\u0001\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b\t\n\u000b??\u0000?\u0010\u0000\u0002\u0001\u0003\u0003\u0002\u0004\u0003\u0005\u0005\u0004\u0004\u0000\u0000\u0001}\u0001\u0002\u0003\u0000\u0004\u0011\u0005\u0012!1A\u0006\u0013Qa\u0007\"q\u00142???\b#B??\u0015R??$3br?\t\n\u0016\u0017\u0018\u0019\u001a%&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz???????????????????????????????????????????????????????????????????????????\u0000\u001f\u0001\u0000\u0003\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b\t\n\u000b??\u0000?\u0011\u0000\u0002\u0001\u0002\u0004\u0004\u0003\u0004\u0007\u0005\u0004\u0004\u0000\u0001\u0002w\u0000\u0001\u0002\u0003\u0011\u0004\u0005!1\u0006\u0012AQ\u0007aq\u0013\"2?\b\u0014B????\t#3R?\u0015br?\n\u0016$4?%?\u0017\u0018\u0019\u001a&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz
use this code,
String dataValue="";
byte[] bytes = dataValue.getBytes();
Bitmap bmp= BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
Try with this.
You can write the byte array directly to file and do whatever you want with the file:
public void writeToFile(byte[] data, String fileName) throws IOException{
FileOutputStream out = new FileOutputStream(fileName);
out.write(data);
out.close();
}
Also if you have binary stream instance, you can create a bitmap instance directly from the stream, you can use BitmapFactory and convert to bitmap:
Bitmap image = BitmapFactory.decodeStream(stream);
You can download the image file using the following function, where body is retrofit2.0 responsebody instance:
private void DownloadImage(ResponseBody body) {
try {
InputStream in = null;
FileOutputStream out = null;
try {
in = body.byteStream();
out = new FileOutputStream("/sdcardpath" + "imagefilename.jpg");
int c;
while ((c = in.read()) != -1) {
out.write(c);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
First of all I would like to say, that loading big images strategy is described here. I am aware of the obligation to resize the image to omit OutOfMemoryError. I would like to get bytes from the image to be able to send it through Internet.
public byte[] getAttachment(Context context, String fullFilePath) {
byte[] fileBytes = mFileUtil.readFileAsBytes(fullFilePath);
if (fileBytes == null) {
Logger.i("Unable to get bytes, trying through content resolver");
try {
fileBytes = mFileUtil.readFileFromContentResolver(context, fullFilePath);
} catch (OutOfMemoryError e) {
Uri imageUri = Uri.parse(fullFilePath);
if (checkIfFileIsImage(context, imageUri)) {
try {
InputStream stream = context.getContentResolver().openInputStream(imageUri);
if (stream == null) {
return null;
}
BitmapFactory.Options options = getOptions(stream, 2000, 2000);
stream.close();
stream = context.getContentResolver().openInputStream(imageUri);
if (stream == null) {
return null;
}
Bitmap bitmap = BitmapFactory.decodeStream(stream, null, options);
bitmap = rotateBitmap(context, imageUri, bitmap);
stream.close();
fileBytes = convertBitmapToArray(bitmap);
} catch (Exception e1) {
Logger.e("Unable to get bytes using fallback method, attachment " +
"will not be added");
} catch (OutOfMemoryError e2) {
Logger.e("Unable to get bytes using fallback method, because " +
"attachment is too big. Attachment will not be added");
}
}
System.gc();
}
}
return fileBytes;
}
FileUtil.class
public byte[] readFileAsBytes(String fileName) {
File originalFile = new File(fileName);
byte[] bytes = null;
try {
FileInputStream fileInputStreamReader = new FileInputStream(originalFile);
bytes = new byte[(int) originalFile.length()];
fileInputStreamReader.read(bytes);
} catch (IOException e) {
}
return bytes;
}
public byte[] readFileFromContentResolver(Context context, String fileName) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
InputStream is = null;
InputStream inputStream = null;
try {
inputStream = context.getContentResolver().openInputStream(Uri.parse(fileName));
is = new BufferedInputStream(inputStream);
byte[] data = new byte[is.available()];
is.read(data);
bos.write(data);
} catch (Exception e) {
} finally {
try {
if (is != null) {
is.close();
}
if (inputStream != null) {
inputStream.close();
}
} catch (IOException e1) {
}
}
return bos.toByteArray();
}
As you can see the aim of this code is to get byte[] from Bitmap unlike here. It works without problems in almost any case. However it is especially error prone on low-end devices with older Android systems (but also very rarely).
I don't like the idea of setting largeHeap inside AndroidManifest.xml as this is just masking the problem rather than cope with it. I also would not like to send even smaller images.
Could this piece of code be improved in any other way in order to get rid of OutOfMemoryError?
I am using volley library and displaying image successfully. I want to get same downloaded image from cache . This is my code :
private Bitmap getBitmapFromUrl(String url){
String str = "" ;
Bitmap bitmap = null ;
byte[] bytes = null ;
Cache cache = AppController.getInstance().getRequestQueue().getCache();
Entry entry = cache.get(url);
try {
str = new String(entry.data, "UTF-8");
bytes = str.getBytes("UTF_8") ;
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
bitmap = BitmapFactory.decodeByteArray( bytes, 0,bytes.length,options);
Log.i(PostItemAdapter.class.getSimpleName(), bitmap+"");
return bitmap ;
}
My issue is that the bitmap object is null .
Can any one tell me why ? thanks in advance .
My problem solved using the aid of this great link where I copied the three files in their images package :
DiskLruImageCache
ImageCacheManager
BitmapLruImageCache
Also I copied RequestManager file. Also there was an issue faced me in the DiskLruImageCache when creating the key from the URL, and I solved this by replacing few lines in this file.
The solution
-old code:
First
#Override
public Bitmap getBitmap( String key ) {
Bitmap bitmap = null;
DiskLruCache.Snapshot snapshot = null;
try {
snapshot = mDiskCache.get( key );
....... etc
Second
#Override
public void putBitmap( String key, Bitmap data ) {
DiskLruCache.Editor editor = null;
try {
editor = mDiskCache.edit( key );
......etc
-new code:
First
#Override
public Bitmap getBitmap( String key ) {
Bitmap bitmap = null;
DiskLruCache.Snapshot snapshot = null;
try {
snapshot = mDiskCache.get( ImageCacheManager.getInstance().createKey(key) );
....etc
Second
#Override
public void putBitmap( String key, Bitmap data ) {
DiskLruCache.Editor editor = null;
try {
editor = mDiskCache.edit( ImageCacheManager.getInstance().createKey(key) );
.....etc
Note : All this modification in DiskLruImageCache , Beside the caching you can save images to SD Card by this function :
private void saveImageToSD(Bitmap bmp) {
bytes = new ByteArrayOutputStream();
bmp.compress(mCompressFormat, 90, bytes);
file = new File(Environment.getExternalStorageDirectory()+File.separator+"myImage"+(++i)+".jpg");
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
/*--- create a new FileOutputStream and write bytes to file ---*/
try {
fos = new FileOutputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
try {
fos.write(bytes.toByteArray());
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
And calling to this function be inside the getBitmap(String URL) function witch inside the DiskLruImageCache file .
I am new in Android.
I am downloading images from the internet in the ListView .I getting the url in the file object but when I send it into the Bitmap object the bitmap object is return null means image is not loaded into the bitmap object.please reply me. the code is here:
private Bitmap getBitmap(String url) {
String filename = String.valueOf(url.hashCode());
File f = new File(cacheDir, filename);
// here in f i getting image url
// here in bitmap the url is not loaded & get null
Bitmap bitmap = BitmapFactory.decodeFile(f.getPath());
if(bitmap != null) return bitmap;
// Nope, have to download it
try {
bitmap =
BitmapFactory.decodeStream(new URL(url).openConnection().getInputStream());
// save bitmap to cache for later
writeFile(bitmap, f);
return bitmap;
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}
private void writeFile(Bitmap bmp, File f) {
FileOutputStream out = null;
try {
out = new FileOutputStream(f);
bmp.compress(Bitmap.CompressFormat.PNG, 80, out);
} catch (Exception e) {
e.printStackTrace();
}
finally {
try { if (out != null ) out.close(); }
catch(Exception ex) {}
}
}
I do not think you are downloading properly the bitmap.
CODE
This is a function I created that will take a url from you and it will return a drawable!
It will save it to a file and get it if it exists
If not, it will download it and return the drawable.
You can easily edit it to save file to your folder instead.
/**
* Pass in an image url to get a drawable object
*
* #return a drawable object
*/
private static Drawable getDrawableFromUrl(final String url) {
String filename = url;
filename = filename.replace("/", "+");
filename = filename.replace(":", "+");
filename = filename.replace("~", "s");
final File file = new File(Environment.getExternalStorageDirectory()
+ File.separator + filename);
boolean exists = file.exists();
if (!exists) {
try {
URL myFileUrl = new URL(url);
HttpURLConnection conn = (HttpURLConnection) myFileUrl
.openConnection();
conn.setDoInput(true);
conn.connect();
InputStream is = conn.getInputStream();
final Bitmap result = BitmapFactory.decodeStream(is);
is.close();
new Thread() {
public void run() {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
result.compress(Bitmap.CompressFormat.JPEG, 40, bytes);
try {
if (file.createNewFile()){
//
}
else{
//
}
FileOutputStream fo;
fo = new FileOutputStream(file);
fo.write(bytes.toByteArray());
fo.flush();
fo.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
BitmapDrawable returnResult = new BitmapDrawable(result);
return returnResult;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
else {
return new BitmapDrawable(BitmapFactory.decodeFile(file.toString()));
}
}
Only thing I can think of here is that you're missing INTERNET permission in your manifest.
Try adding <uses-permission android:name="android.permission.INTERNET" /> in your AndroidManifest.xml if it's not there yet
I have a text file added as a raw resource. The text file contains text like:
b) IF APPLICABLE LAW REQUIRES ANY WARRANTIES WITH RESPECT TO THE
SOFTWARE, ALL SUCH WARRANTIES ARE
LIMITED IN DURATION TO NINETY (90)
DAYS FROM THE DATE OF DELIVERY.
(c) NO ORAL OR WRITTEN INFORMATION OR
ADVICE GIVEN BY VIRTUAL ORIENTEERING,
ITS DEALERS, DISTRIBUTORS, AGENTS OR
EMPLOYEES SHALL CREATE A WARRANTY OR
IN ANY WAY INCREASE THE SCOPE OF ANY
WARRANTY PROVIDED HEREIN.
(d) (USA only) SOME STATES DO NOT
ALLOW THE EXCLUSION OF IMPLIED
WARRANTIES, SO THE ABOVE EXCLUSION MAY
NOT APPLY TO YOU. THIS WARRANTY GIVES
YOU SPECIFIC LEGAL RIGHTS AND YOU MAY
ALSO HAVE OTHER LEGAL RIGHTS THAT
VARY FROM STATE TO STATE.
On my screen I have a layout like this:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_weight="1.0"
android:layout_below="#+id/logoLayout"
android:background="#drawable/list_background">
<ScrollView android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView android:id="#+id/txtRawResource"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="3dip"/>
</ScrollView>
</LinearLayout>
The code to read the raw resource is:
TextView txtRawResource= (TextView)findViewById(R.id.txtRawResource);
txtDisclaimer.setText(Utils.readRawTextFile(ctx, R.raw.rawtextsample);
public static String readRawTextFile(Context ctx, int resId)
{
InputStream inputStream = ctx.getResources().openRawResource(resId);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
int i;
try {
i = inputStream.read();
while (i != -1)
{
byteArrayOutputStream.write(i);
i = inputStream.read();
}
inputStream.close();
} catch (IOException e) {
return null;
}
return byteArrayOutputStream.toString();
}
The text is shown but after each line I get the strange characters []. How can I remove the characters? I think it's a newline.
You can use this:
try {
Resources res = getResources();
InputStream in_s = res.openRawResource(R.raw.help);
byte[] b = new byte[in_s.available()];
in_s.read(b);
txtHelp.setText(new String(b));
} catch (Exception e) {
// e.printStackTrace();
txtHelp.setText("Error: can't show help.");
}
What if you use a character-based BufferedReader instead of byte-based InputStream?
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String line = reader.readLine();
while (line != null) {
...
line = reader.readLine();
}
Don't forget that readLine() skips the new-lines!
Well with Kotlin u can do it just in one line of code:
resources.openRawResource(R.raw.rawtextsample).bufferedReader().use { it.readText() }
Or even declare extension function:
fun Resources.getRawTextFile(#RawRes id: Int) =
openRawResource(id).bufferedReader().use { it.readText() }
And then just use it straightaway:
val txtFile = resources.getRawTextFile(R.raw.rawtextsample)
If you use IOUtils from apache "commons-io" it's even easier:
InputStream is = getResources().openRawResource(R.raw.yourNewTextFile);
String s = IOUtils.toString(is);
IOUtils.closeQuietly(is); // don't forget to close your streams
Dependencies: http://mvnrepository.com/artifact/commons-io/commons-io
Maven:
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
Gradle:
'commons-io:commons-io:2.4'
Rather do it this way:
// reads resources regardless of their size
public byte[] getResource(int id, Context context) throws IOException {
Resources resources = context.getResources();
InputStream is = resources.openRawResource(id);
ByteArrayOutputStream bout = new ByteArrayOutputStream();
byte[] readBuffer = new byte[4 * 1024];
try {
int read;
do {
read = is.read(readBuffer, 0, readBuffer.length);
if(read == -1) {
break;
}
bout.write(readBuffer, 0, read);
} while(true);
return bout.toByteArray();
} finally {
is.close();
}
}
// reads a string resource
public String getStringResource(int id, Charset encoding) throws IOException {
return new String(getResource(id, getContext()), encoding);
}
// reads an UTF-8 string resource
public String getStringResource(int id) throws IOException {
return new String(getResource(id, getContext()), Charset.forName("UTF-8"));
}
From an Activity, add
public byte[] getResource(int id) throws IOException {
return getResource(id, this);
}
or from a test case, add
public byte[] getResource(int id) throws IOException {
return getResource(id, getContext());
}
And watch your error handling - don't catch and ignore exceptions when your resources must exist or something is (very?) wrong.
#borislemke you can do this by similar way like
TextView tv ;
findViewById(R.id.idOfTextView);
tv.setText(readNewTxt());
private String readNewTxt(){
InputStream inputStream = getResources().openRawResource(R.raw.yourNewTextFile);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
int i;
try {
i = inputStream.read();
while (i != -1)
{
byteArrayOutputStream.write(i);
i = inputStream.read();
}
inputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return byteArrayOutputStream.toString();
}
This is another method which will definitely work, but I cant get it to read multiple text files to view in multiple textviews in a single activity, anyone can help?
TextView helloTxt = (TextView)findViewById(R.id.yourTextView);
helloTxt.setText(readTxt());
}
private String readTxt(){
InputStream inputStream = getResources().openRawResource(R.raw.yourTextFile);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
int i;
try {
i = inputStream.read();
while (i != -1)
{
byteArrayOutputStream.write(i);
i = inputStream.read();
}
inputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return byteArrayOutputStream.toString();
}
Here goes mix of weekens's and Vovodroid's solutions.
It is more correct than Vovodroid's solution and more complete than weekens's solution.
try {
InputStream inputStream = res.openRawResource(resId);
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
try {
StringBuilder result = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
result.append(line);
}
return result.toString();
} finally {
reader.close();
}
} finally {
inputStream.close();
}
} catch (IOException e) {
// process exception
}
Here is an implementation in Kotlin
try {
val inputStream: InputStream = this.getResources().openRawResource(R.raw.**)
val inputStreamReader = InputStreamReader(inputStream)
val sb = StringBuilder()
var line: String?
val br = BufferedReader(inputStreamReader)
line = br.readLine()
while (line != null) {
sb.append(line)
line = br.readLine()
}
br.close()
var content : String = sb.toString()
Log.d(TAG, content)
} catch (e:Exception){
Log.d(TAG, e.toString())
}
Here is a simple method to read the text file from the raw folder:
public static String readTextFile(Context context,#RawRes int id){
InputStream inputStream = context.getResources().openRawResource(id);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
byte buffer[] = new byte[1024];
int size;
try {
while ((size = inputStream.read(buffer)) != -1)
outputStream.write(buffer, 0, size);
outputStream.close();
inputStream.close();
} catch (IOException e) {
}
return outputStream.toString();
}
1.First create a Directory folder and name it raw inside the res folder
2.create a .txt file inside the raw directory folder you created earlier and give it any name eg.articles.txt....
3.copy and paste the text you want inside the .txt file you created"articles.txt"
4.dont forget to include a textview in your main.xml
MainActivity.java
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_gettingtoknowthe_os);
TextView helloTxt = (TextView)findViewById(R.id.gettingtoknowos);
helloTxt.setText(readTxt());
ActionBar actionBar = getSupportActionBar();
actionBar.hide();//to exclude the ActionBar
}
private String readTxt() {
//getting the .txt file
InputStream inputStream = getResources().openRawResource(R.raw.articles);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
try {
int i = inputStream.read();
while (i != -1) {
byteArrayOutputStream.write(i);
i = inputStream.read();
}
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
return byteArrayOutputStream.toString();
}
Hope it worked!
InputStream is=getResources().openRawResource(R.raw.name);
BufferedReader reader=new BufferedReader(new InputStreamReader(is));
StringBuffer data=new StringBuffer();
String line=reader.readLine();
while(line!=null)
{
data.append(line+"\n");
}
tvDetails.seTtext(data.toString());
Here's a one liner for you:
String text = new BufferedReader(
new InputStreamReader(getResources().openRawResource(R.raw.my_file)))
.lines().reduce("\n", (a,b) -> a+b);
val inputStream: InputStream = resources.openRawResource(R.raw.product_json)
val reader: Reader = BufferedReader(InputStreamReader(inputStream, "utf-8"))
val writer: Writer = StringWriter()
val buffer = CharArray(1024)
reader.use { it ->
var n: Int
while (it.read(buffer).also { n = it } != -1) {
writer.write(buffer, 0, n)
}
}
val stringVal = writer.toString()