Problem:
Using an Android device, without internet / network connection, I have to print images to a bluetooth enabled printer.
Be aware that this is the business case — I cannot use Google Cloud Print, nor can I use PrinterShare or anything else like that. The data generated by the app is medical in nature and must be kept confidential and within the app.
What I’ve accomplished:
Generating PCL data (text only, no images) to send to a bluetooth connection that the printer can process and output.
What I’ve tried:
Generating PCL data (image) using the Android ImageMagick port (found here: https://github.com/paulasiimwe/Android-ImageMagick) and sending the generated PCL data to the bluetooth connection.
Result:
Gibberish, but gibberish that appears to be the right dimensions of the image I am trying to print.
==============
My hypothesis is that there’s something slightly off in my implementation of the conversion, but I’m not sure what it is.
Sample Code:
NOTE: this is proof of concept work and captures an image from the Assets dir, makes it available, and then converts it.
// Attempt to get image file from Assets folder
AssetManager assetManager = context.getAssets();
InputStream istr = assetManager.open("test.jpg");
Bitmap bitmap = BitmapFactory.decodeStream(istr);
// Access External Storage Directory and save file
String root = Environment.getExternalStorageDirectory().toString();
File tempDirectory = new File(root + "/temp");
tempDirectory.mkdirs();
String fileName = "test.jpg";
File file = new File (tempDirectory, fileName);
try {
FileOutputStream out = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
} catch (Exception exception) {
// Exception found
}
// Capture file of recently saved image, convert to PCL
try{
ImageInfo originalInfo = new ImageInfo(Environment.getExternalStorageDirectory().getAbsolutePath() + "/temp/test.jpg");
MagickImage mImage = new MagickImage(originalInfo);
String newInfoPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/temp/test.pcl";
mImage.setFileName(newInfoPath);
mImage.setImageFormat("pcl");
ImageInfo newInfo = new ImageInfo(newInfoPath);
mImage.writeImage(newInfo);
} catch (MagickException exception) {
// Exception found
}
I then retrieve the PCL file and send it to the bluetooth connection (using another method that works using standard PCL files), but as mentioned the output is gibberish.
I feel like I’m missing something simple, but I’m just not seeing it.
Also, I am seeing the following in LogCat that may / may not be related, but I haven't been able to find any information about resolving this nor can I determine if it's anything more than a warning.
V/Magick: ThrowException
V/Magick: severity: 395
V/Magick: reason: UnableToOpenConfigureFile `policy.xml' # warning/configure.c/GetConfigureOptions/589
V/Magick: Attempting to read from file /storage/emulated/0/temp/test.jpg
V/Magick: ThrowException
V/Magick: severity: 395
V/Magick: reason: UnableToOpenConfigureFile `magic.xml' # warning/configure.c/GetConfigureOptions/589
V/Magick: OpenPixelCache()
V/Magick: - cache_info->columns: 144
V/Magick: - cache_info->rows: 144
V/Magick: - cache_info->offset: 0
V/Magick: - cache_info->length: 165888
V/Magick: - length: 207360
V/Magick: - create memory pixel cache
V/Magick: ReadImage completed
Does anyone have any experience with this or can anyone point me in the right direction?
Related
I modified some code to write a Bitmap to internal storage (Android) that previously wrote to external storage successfully. But compress() is now returning false. Unfortunately the docs do not describe conditions that are likely to cause this, and of course since no exception being thrown there's no help there.
Below is my code.
// Only change made was to the line immediately below, now commented out
// File directory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES + "/AIL_SCANS"); //Creates app specific folder
File directory = contextIn.getDir("my_pics", Context.MODE_PRIVATE);
if (!directory.exists())
directory.mkdirs();
File file = new File(directory, sFilenameIn + ".jpg");
FileOutputStream os = new FileOutputStream(file);
if (!imageIn.compress(Bitmap.CompressFormat.JPEG, 100, os))
Log.e("Error", " compress() failed (returned false)");
os.flush();
os.getFD().sync();
os.close();
Log.e("Success", " Profit!!");
My code created the Bitmap as ARGB_8888 (see below) so a couple of other Stack Overflow posts reporting a similar failure do not seem to apply here.
bmp = Bitmap.createBitmap(arrPixels, widh, height, Bitmap.Config.ARGB_8888);
An example of some code that apparently has worked well for a large number of Stack Overflow users looks almost exactly like mine. Saving and Reading Bitmaps/Images from Internal memory in Android
If you are running Android 6.0 >= you have to ask for permissions before you write into the storage.
Refer to this documentation Ask for permissions
I'm working on a rooted android device. I'm trying to capture the screen and store the result in Bitmap for later usage.
String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath();
path += "/img.png";
Process sh = Runtime.getRuntime().exec("su", null,null);
OutputStream os = sh.getOutputStream();
os.write(("/system/bin/screencap -p " + path).getBytes("ASCII"));
os.flush();
os.close();
sh.waitFor();
final Bitmap x = BitmapFactory.decodeFile(path);
What I'm doing here is naming a path for a new image and capturing the screen using the command /system/bin/screencap -p FILEPATH. Then I read the image I stored in that file and use it in the bitmap.
My problem with my current code is that it's slow(not suitable for a real-time application). I'm now trying to make it faster. Instead of saving the captured picture into file and then reading it again from the program, I want to read it directly from the result of Runtime.getRuntime().exec(...)
In the description of the command screencap, I found that I can use it without specifying the output file name, and in this case the results will be printed to stdout.
I tried several codes to read the result byte array to use it directly in my code
final Bitmap x = BitmapFactory.decodeByteArray(resultArrayByte, 0, resultArrayByte.length);
but none of the codes worked with me.
How can I use sh's input/output streams to get the result byte array directly without saving the output into a file then loading it again?
Take a Look here, in this link you can find a library called ASL
a lot of questions in this post, i'm confused :)
i hope this link is useful for your requirements.
I´m working on a project related with image recognition using MATLAB and I'm currently using an Android app to help with some pre-processing steps. I thought it was going to be easy to work with matrices instead of bitmaps. I finally managed to finish my algorithm and to import it to Eclipse. The problem is that I realize that I don't know how to convert a Bitmap image into something that MATLAB can read in for the purposes of my algorithm.
Do you have any ideas on how I can do this?
If I'm interpreting your question correctly, you have an image stored in the Bitmap class and you want to save this to file locally on your Android device. You then want to load this image into MATLAB for your image recognition algorithm.
Given the fact that your image is in memory via Android, you can use the method compress: http://developer.android.com/reference/android/graphics/Bitmap.html#compress(android.graphics.Bitmap.CompressFormat, int, java.io.OutputStream
You'd then use this and save the image to file, and then you can load it into MATLAB, using imread for example.
Here's some sample code you could write for your Android app. Assuming your Bitmap instance is stored in a variable called bmp, do:
FileOutputStream out = null; // For writing to the device
String filename = "out.png"; // Output file name
// Full path to save
// This accesses the pictures directory of your device and saves the file there
String output = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), filename);
try {
out = new FileOutputStream(filename); // Open up a new file stream
// Save the Bitmap instance to file
// First param - type of image
// Second param - Compression factor
// Third param - The full path to the file
// Note: PNG is lossless, so the compression factor (100) is ignored
bmp.compress(Bitmap.CompressFormat.PNG, 100, out);
}
// Catch any exceptions that happen
catch (Exception e) {
e.printStackTrace();
}
// Execute this code even if exception happens
finally {
try {
// Close the file if it was open to write
if (out != null)
out.close();
}
// Catch any exceptions with the closing here
catch (IOException e) {
e.printStackTrace();
}
}
The above code will save the image to your default Pictures directory on your device. Once you pull out that image, you can read the image into MATLAB by using imread:
im = imread('out.png');
im would thus be the raw RGB pixels of the image that you can now use for your image recognition algorithm.
Okay, I seem to be having a small issue with R.drawable.balloons. I'm trying to use a template for building a private external storage file that I found on Android Developer, but balloons keeps giving an error (cannot be resolved or is not a field). I was wondering if I could get some help fixing it.
Here's the code section it sits in:
void createExternalStoragePrivateFile() {
// Create a path where we will place our private file on external
// storage.
File file = new File(getExternalFilesDir(null), "DemoFile.jpg");
try {
/*
Very simple code to copy a picture from the application's
resource into the external file. Note that this code does
no error checking, and assumes the picture is small (does not
try to copy it in chunks). Note that if external storage is
not currently mounted this will silently fail.
*/
// Creates file to stream picture
OutputStream os = new FileOutputStream(file);
// Allows app to accept the picture
InputStream is = getResources().openRawResource(R.drawable.balloons);
byte[] data = new byte[is.available()];
is.read(data);
os.write(data);
is.close();
os.close();
} catch (IOException e) {
// Unable to create file, likely because external storage is
// not currently mounted.
Log.w("ExternalStorage", "Error writing " + file, e);
}
}
A heads up, in case I get called out for being a copy/paster, this is only supposed to be a template, but I would like to test that it works before I make changes. Sorry.
You need an image named balloons in the res\drawable folder of your project (or any of its variants, such as drawable-hdpi, &c). The R class is autogenerated.
See How do I add R drawable android?
The problem is this:
I make an internet connection to some url and receive an HttpResponse with an app_example.apk.
Then I want to create a file (an .apk)
in the sdcard with this data so that this downloaded application
can be installed later.
How can I convert the HttpResponse to an .apk file?
Let's clear some details:
I have to get this apk file through an internet connection to my server
I don't want to install this applications I receive on the sdcard
All of this has to be done in my code, I cannot use android market
I am currently writing to that file.
What I'm doing is converting the HttpResponse to a byte[ ],
then that byte[ ] is written to a file (an .apk) using an ObjectOutputStream.
Like this:
// byte[] appByteArray - already has the internet response converted in bytes
try {
file = new File(Environment.getExternalStorageDirectory()+"/"+appName+".apk");
file.createNewFile();
FileOutputStream stream = null;
stream = new FileOutputStream(file, false);
ObjectOutputStream objectOut =
new ObjectOutputStream(new BufferedOutputStream(stream));
objectOut.writeObject(appByteArray);
objectOut.close();
} catch (Exception e) {
e.printStackTrace();
}
In the end, the file is created
and has the received content.
When I try to install it,
through a VIEW intent (using the default installer)
I get a parse error saying that it could not find the AndroidManifest.xml.
I think that in some step along the way, the received data is being corrupted.
Do you have another method to solve this?
Many thanks
Don't use an ObjectOutputStream, byte array is serialized as Object, not written as raw data.
Are you sure that you have SD card write permission? android.permission.WRITE_EXTERNAL_STORAGE
Don't write into SD card root directory. Number of files in root dir can be limited. Instead create you app subdirectory on SD CARD.
This code works for me:
try {
String filePath = Environment.getExternalStorageDirectory()
+ "/myappdir/" + appName + ".apk";
File file = new File(filePath);
file.getParentFile().mkdirs();
file.createNewFile();
BufferedOutputStream objectOut = new BufferedOutputStream(
new FileOutputStream(file));
objectOut.write(appByteArray);
objectOut.close();
} catch (Exception e) {
e.printStackTrace();
}
This may not be the core problem, but I don't think you want to wrap stream in an ObjectOutputStream, since that is used for object serialization. It could be that it is adding extra data to the file so it can be deserialized with ObjectInputStream.
I would try pulling the apk off of the emulator (or device) and check it's MD5 versus the file on the server to make sure that the bits are being written out correctly.
Take a look at Pavel P's answer.
Also, I would note that your idea of installing the APK using the VIEW intent action does work, as I have tested this technique in the past.
However, unless the user has explicitly gone into Settings → Applications and selected "Allow non-Market applications", your installation will fail and the user will just see a screen telling them that for security reasons the installation has been blocked.
Basically you really need to rely on having fairly tech-savvy users who are willing to overlook a scary security warning and go and disable that setting.