Invoking a method in a fragment through a LocalBroadcastManager - android

I'm building an app with 2 fragments.
1st Fragment: ImageView and 2 TextViews
2nd Fragment: 2 EditTexts and 3 Buttons
In the 2nd Fragment, I have a "Save" Button. In the onClick of this button, I am trying to send a local broadcast:
btnSave.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
localBroadcastManager.sendBroadcast(localIntent);
}
});
And this is my intent:
final LocalBroadcastManager localBroadcastManager = LocalBroadcastManager
.getInstance(Objects.requireNonNull(getContext()));
final Intent localIntent = new Intent("CUSTOM_ACTION");
The point of this is so that the 1st fragment picks it up and executes a method to save the Image as a bitmap with its captions (that's what the 2 TextViews are for). This is my attempt:
private BroadcastReceiver listener = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent ) {
String data = intent.getStringExtra("DATA");
Toast.makeText(context, data + " received", Toast.LENGTH_SHORT).show();
createAndSaveBitmap(topTextView.getText().toString(), bottomTextView.getText().toString(), memeBitmap, memeCanvas, memePaint, imageView, imageUri);
}
};
public void createAndSaveBitmap(String top, String bottom, Bitmap bitmap,
Canvas canvas, Paint paint, ImageView imageView, Uri imageUri) {
try {
memeBitmap = BitmapFactory.decodeStream(context.getContentResolver().openInputStream(imageUri))
.copy(Bitmap.Config.ARGB_8888, true); }
catch (FileNotFoundException e) { e.printStackTrace(); }
canvas = new Canvas(memeBitmap);
paint = new Paint();
canvas.drawText(top, 0, 0, paint);
canvas.drawText(bottom, 0, memeCanvas.getHeight() - 10, paint);
imageView.setImageBitmap(memeBitmap);
if(bitmap != null){
File file = Environment.getExternalStorageDirectory();
File newFile = new File(file, "test.jpg");
try {
FileOutputStream fileOutputStream = new FileOutputStream(newFile);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fileOutputStream);
fileOutputStream.flush();
fileOutputStream.close();
}
catch (FileNotFoundException e) {e.printStackTrace();}
catch (IOException e) { e.printStackTrace(); }
}
}
When I run the app, nothing happens when I click the "Save" button. Doesn't download the image, nor does it crash. Since there is no error stacktrace, I can't see where I'm going wrong.

Make sure that you are calling this in your receiving fragment's onResume.
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(
listener,
new IntentFilter("CUSTOM_ACTION")
);
and this in onPause
LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(listener);

Related

How to take screenshot of dialog in Android programmatically?

I have Android application which interacts with Web Server. When data is sent from phone to server, there is a bit of work with data (10-20 secs) and after that I get result back to phone. And i display that result in dialog with 2 choices. One choice is "OK" and it means that user is fine with result and dismiss the dialog. The other choice makes a screenshot of that results. And when I press this button I don't get picture of dialog, i get picture of layout which is behind that dialog.
My code behind this is
//this method is called on onPostExecute of async task
public void recieveResult (final Activity act,String result){
new AlertDialog.Builder(act)
.setTitle("Data - status")
.setMessage(result)
.setNegativeButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
})
.setPositiveButton("Save picture", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Bitmap bitmap = takeScreenshot(act);
saveBitmap(bitmap,act);
Toast.makeText(act,"Saved",Toast.LENGTH_LONG).show();
dialog.dismiss();
}
})
.show();
}
public Bitmap takeScreenshot(Activity act) {
View rootView = act.findViewById(android.R.id.content).getRootView();
rootView.setDrawingCacheEnabled(true);
return rootView.getDrawingCache();
}
public void saveBitmap(Bitmap bitmap,Activity act) {
String timeStamp = new SimpleDateFormat("MMyyyydd_HHmmss").format(new Date());
String imageFileName = "/screenshot_"+timeStamp+"_.png";
File storage = Environment.getExternalStoragePublicDirectory("Screens");
if (!storage.exists())
{
Toast.makeText(act, "Directory made", Toast.LENGTH_LONG).show();
storage.mkdirs();
}
File imagePath = new File(storage.getPath() + imageFileName);
FileOutputStream fos;
try {
fos = new FileOutputStream(imagePath);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.flush();
fos.close();
} catch (FileNotFoundException e) {
Log.e("GREC", e.getMessage(), e);
} catch (IOException e) {
Log.e("GREC", e.getMessage(), e);
}
}
My result of picture is just screen without dialog. How to get picture of dialog in it?
Try obtaining the Windows's decor view
then get its drawing cache bitmap as you implemented.
Dialog has it's own window ( different form activity's window ), you can use dialog.getWindow() method to get dialog's window.
so here is the screenshot code:
private AlertDialog dialog;
public void showDialog(View view) {
dialog = new AlertDialog.Builder(this)
.setTitle("Titel")
.setMessage("some content")
.setPositiveButton("Screenshot", (d, which) -> {
Bitmap bitmap = screenshot(dialog);
// you can save the bitmap or display in an ImageView
}).create();
dialog.show();
}
private Bitmap screenshot(Dialog dialog) {
Window window = dialog.getWindow();
View decorView = window.getDecorView();
Bitmap bitmap = Bitmap.createBitmap(decorView.getWidth(), decorView.getHeight(), Bitmap.Config.ARGB_8888);
decorView.draw(new Canvas(bitmap));
return bitmap;
}
try this code
String picId=String.valueOf(nu);
String myfile="meter"+picId+".jpeg";
BitmapDrawable bitmapDrawable = null;
Toast.makeText(getActivity(),"success full store image gallery",Toast.LENGTH_SHORT).show();
Date now = new Date();
android.text.format.DateFormat.format("yyyy-MM-dd_hh:mm:ss", now);
try {
File dir_image = new File(Environment.getExternalStorageDirectory()+//<---
File.separator+"SoundMeter"); //23-1-16 //<---
dir_image.mkdirs();
// image naming and path to include sd card appending name you choose for file
// String mPath = Environment.getExternalStorageDirectory().toString() + "/" + now + ".jpg";
// create bitmap screen capture
View v1 = surfaceView.getRootView();
v1.setDrawingCacheEnabled(true);
Bitmap bitmap = Bitmap.createBitmap(v1.getDrawingCache());
/* bitmapDrawable = new BitmapDrawable(bitmap);*/
v1.setDrawingCacheEnabled(false);
// File imageFile = new File(mPath); //file path 23-1-16
File imageFile = new File(dir_image,myfile);
FileOutputStream outputStream = new FileOutputStream(imageFile);
int quality = 100;
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outputStream);
outputStream.flush();
outputStream.close();
openScreenshot(imageFile);
} catch (Throwable e) {
// Several error may come out with file handling or OOM
e.printStackTrace();
}
btnCaptured1.setVisibility(View.VISIBLE);
btnCaptured.setVisibility(View.VISIBLE);
//btnCaptured.setBackgroundDrawable(bitmapDrawable);
}
});
}
else
{
Toast.makeText(getActivity().getApplicationContext(), "No Connection", Toast.LENGTH_LONG).show();
}

Capture screen shot of GoogleMap Android API V2

Final Update
The feature request has been fulfilled by Google. Please see this answer below.
Original Question
Using the old version of the Google Maps Android API, I was able to capture a screenshot of the google map to share via social media. I used the following code to capture the screenshot and save the image to a file and it worked great:
public String captureScreen()
{
String storageState = Environment.getExternalStorageState();
Log.d("StorageState", "Storage state is: " + storageState);
// image naming and path to include sd card appending name you choose for file
String mPath = this.getFilesDir().getAbsolutePath();
// create bitmap screen capture
Bitmap bitmap;
View v1 = this.mapView.getRootView();
v1.setDrawingCacheEnabled(true);
bitmap = Bitmap.createBitmap(v1.getDrawingCache());
v1.setDrawingCacheEnabled(false);
OutputStream fout = null;
String filePath = System.currentTimeMillis() + ".jpeg";
try
{
fout = openFileOutput(filePath,
MODE_WORLD_READABLE);
// Write the string to the file
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fout);
fout.flush();
fout.close();
}
catch (FileNotFoundException e)
{
// TODO Auto-generated catch block
Log.d("ImageCapture", "FileNotFoundException");
Log.d("ImageCapture", e.getMessage());
filePath = "";
}
catch (IOException e)
{
// TODO Auto-generated catch block
Log.d("ImageCapture", "IOException");
Log.d("ImageCapture", e.getMessage());
filePath = "";
}
return filePath;
}
However, the new GoogleMap object used by V2 of the api does not have a "getRootView()" method like MapView does.
I tried to do this:
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.basicMap);
View v1 = mapFragment.getView();
But the screenshot that I get does not have any map content and looks like this:
Has anyone figured out how to take a screenshot of the new Google Maps Android API V2?
Update
I also tried to get the rootView this way:
View v1 = getWindow().getDecorView().getRootView();
This results in a screenshot that includes the action bar at the top of the screen, but the map is still blank like the screenshot I attached.
Update
A feature request has been submitted to Google. Please go star the feature request if this is something you want google to add in the future: Add screenshot ability to Google Maps API V2
Update - Google has added a snapshot method**!:
The feature request for a method to take a screen shot of the Android Google Map API V2 OpenGL layer has been fulfilled.
To take a screenshot, simply implement the following interface:
public abstract void onSnapshotReady (Bitmap snapshot)
and call:
public final void snapshot (GoogleMap.SnapshotReadyCallback callback)
Example that takes a screenshot, then presents the standard "Image Sharing" options:
public void captureScreen()
{
SnapshotReadyCallback callback = new SnapshotReadyCallback()
{
#Override
public void onSnapshotReady(Bitmap snapshot)
{
// TODO Auto-generated method stub
bitmap = snapshot;
OutputStream fout = null;
String filePath = System.currentTimeMillis() + ".jpeg";
try
{
fout = openFileOutput(filePath,
MODE_WORLD_READABLE);
// Write the string to the file
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fout);
fout.flush();
fout.close();
}
catch (FileNotFoundException e)
{
// TODO Auto-generated catch block
Log.d("ImageCapture", "FileNotFoundException");
Log.d("ImageCapture", e.getMessage());
filePath = "";
}
catch (IOException e)
{
// TODO Auto-generated catch block
Log.d("ImageCapture", "IOException");
Log.d("ImageCapture", e.getMessage());
filePath = "";
}
openShareImageDialog(filePath);
}
};
mMap.snapshot(callback);
}
Once the image is finished being captured, it will trigger the standard "Share Image" dialog so the user can pick how they'd like to share it:
public void openShareImageDialog(String filePath)
{
File file = this.getFileStreamPath(filePath);
if(!filePath.equals(""))
{
final ContentValues values = new ContentValues(2);
values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
values.put(MediaStore.Images.Media.DATA, file.getAbsolutePath());
final Uri contentUriFile = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
final Intent intent = new Intent(android.content.Intent.ACTION_SEND);
intent.setType("image/jpeg");
intent.putExtra(android.content.Intent.EXTRA_STREAM, contentUriFile);
startActivity(Intent.createChooser(intent, "Share Image"));
}
else
{
//This is a custom class I use to show dialogs...simply replace this with whatever you want to show an error message, Toast, etc.
DialogUtilities.showOkDialogWithText(this, R.string.shareImageFailed);
}
}
Documentation is here
Below are the steps to capture screen shot of Google Map V2 with example
Step 1. open Android Sdk Manager (Window > Android Sdk Manager) then Expand Extras now update/install Google Play Services to Revision 10 ignore this step if already installed
Read Notes here https://developers.google.com/maps/documentation/android/releases#august_2013
Step 2. Restart Eclipse
Step 3. import com.google.android.gms.maps.GoogleMap.SnapshotReadyCallback;
Step 4. Make Method to Capture/Store Screen/image of Map like below
public void CaptureMapScreen()
{
SnapshotReadyCallback callback = new SnapshotReadyCallback() {
Bitmap bitmap;
#Override
public void onSnapshotReady(Bitmap snapshot) {
// TODO Auto-generated method stub
bitmap = snapshot;
try {
FileOutputStream out = new FileOutputStream("/mnt/sdcard/"
+ "MyMapScreen" + System.currentTimeMillis()
+ ".png");
// above "/mnt ..... png" => is a storage path (where image will be stored) + name of image you can customize as per your Requirement
bitmap.compress(Bitmap.CompressFormat.PNG, 90, out);
} catch (Exception e) {
e.printStackTrace();
}
}
};
myMap.snapshot(callback);
// myMap is object of GoogleMap +> GoogleMap myMap;
// which is initialized in onCreate() =>
// myMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map_pass_home_call)).getMap();
}
Step 5. Now call this CaptureMapScreen() method where you want to capture the image
in my case i am calling this method on Button click in my onCreate() which is working fine
like:
Button btnCap = (Button) findViewById(R.id.btnTakeScreenshot);
btnCap.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
try {
CaptureMapScreen();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
});
Check Doc here and here
I capctured Map screenshot.It will be helpful
private GoogleMap map;
private static LatLng latLong;
`
public void onMapReady(GoogleMap googleMap) {
map = googleMap;
setMap(this.map);
animateCamera();
map.moveCamera (CameraUpdateFactory.newLatLng (latLong));
map.setOnMapLoadedCallback (new GoogleMap.OnMapLoadedCallback () {
#Override
public void onMapLoaded() {
snapShot();
}
});
}
`
snapShot() method for taking screenshot of map
public void snapShot(){
GoogleMap.SnapshotReadyCallback callback=new GoogleMap.SnapshotReadyCallback () {
Bitmap bitmap;
#Override
public void onSnapshotReady(Bitmap snapshot) {
bitmap=snapshot;
try{
file=new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),"map.png");
FileOutputStream fout=new FileOutputStream (file);
bitmap.compress (Bitmap.CompressFormat.PNG,90,fout);
Toast.makeText (PastValuations.this, "Capture", Toast.LENGTH_SHORT).show ();
}catch (Exception e){
e.printStackTrace ();
Toast.makeText (PastValuations.this, "Not Capture", Toast.LENGTH_SHORT).show ();
}
}
};map.snapshot (callback);
}
My output is below
Edit: this answer is no longer valid - the feature request for screenshots on Google Maps Android API V2 has been fulfilled. See this answer for an example.
Original Accepted Answer
Since the new Android API v2 Maps are displayed using OpenGL, there are no possibilities to create a screenshot.
Since the top voted answer doesnt work with polylines and other overlays on top of the map fragment (What I was looking for), I want to share this solution.
public void captureScreen()
{
GoogleMap.SnapshotReadyCallback callback = new GoogleMap.SnapshotReadyCallback()
{
#Override
public void onSnapshotReady(Bitmap snapshot) {
try {
getWindow().getDecorView().findViewById(android.R.id.content).setDrawingCacheEnabled(true);
Bitmap backBitmap = getWindow().getDecorView().findViewById(android.R.id.content).getDrawingCache();
Bitmap bmOverlay = Bitmap.createBitmap(
backBitmap.getWidth(), backBitmap.getHeight(),
backBitmap.getConfig());
Canvas canvas = new Canvas(bmOverlay);
canvas.drawBitmap(snapshot, new Matrix(), null);
canvas.drawBitmap(backBitmap, 0, 0, null);
OutputStream fout = null;
String filePath = System.currentTimeMillis() + ".jpeg";
try
{
fout = openFileOutput(filePath,
MODE_WORLD_READABLE);
// Write the string to the file
bmOverlay.compress(Bitmap.CompressFormat.JPEG, 90, fout);
fout.flush();
fout.close();
}
catch (FileNotFoundException e)
{
// TODO Auto-generated catch block
Log.d("ImageCapture", "FileNotFoundException");
Log.d("ImageCapture", e.getMessage());
filePath = "";
}
catch (IOException e)
{
// TODO Auto-generated catch block
Log.d("ImageCapture", "IOException");
Log.d("ImageCapture", e.getMessage());
filePath = "";
}
openShareImageDialog(filePath);
} catch (Exception e) {
e.printStackTrace();
}
}
};
;
map.snapshot(callback);
}
private GoogleMap mMap;
SupportMapFragment mapFragment;
LinearLayout linearLayout;
String jobId="1";
File file;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate (savedInstanceState);
setContentView (R.layout.activity_maps);
linearLayout=(LinearLayout)findViewById (R.id.linearlayout);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
mapFragment = (SupportMapFragment)getSupportFragmentManager ()
.findFragmentById (R.id.map);
mapFragment.getMapAsync (this);
//Taking Snapshot of Google Map
}
/**
* Manipulates the map once available.
* This callback is triggered when the map is ready to be used.
* This is where we can add markers or lines, add listeners or move the camera. In this case,
* we just add a marker near Sydney, Australia.
* If Google Play services is not installed on the device, the user will be prompted to install
* it inside the SupportMapFragment. This method will only be triggered once the user has
* installed Google Play services and returned to the app.
*/
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
// Add a marker in Sydney and move the camera
LatLng sydney = new LatLng (-26.888033, 75.802754);
mMap.addMarker (new MarkerOptions ().position (sydney).title ("Kailash Tower"));
mMap.moveCamera (CameraUpdateFactory.newLatLng (sydney));
mMap.setOnMapLoadedCallback (new GoogleMap.OnMapLoadedCallback () {
#Override
public void onMapLoaded() {
snapShot();
}
});
}
// Initializing Snapshot Method
public void snapShot(){
GoogleMap.SnapshotReadyCallback callback=new GoogleMap.SnapshotReadyCallback () {
Bitmap bitmap;
#Override
public void onSnapshotReady(Bitmap snapshot) {
bitmap=snapshot;
bitmap=getBitmapFromView(linearLayout);
try{
file=new File (getExternalCacheDir (),"map.png");
FileOutputStream fout=new FileOutputStream (file);
bitmap.compress (Bitmap.CompressFormat.PNG,90,fout);
Toast.makeText (MapsActivity.this, "Capture", Toast.LENGTH_SHORT).show ();
sendSceenShot (file);
}catch (Exception e){
e.printStackTrace ();
Toast.makeText (MapsActivity.this, "Not Capture", Toast.LENGTH_SHORT).show ();
}
}
};mMap.snapshot (callback);
}
private Bitmap getBitmapFromView(View view) {
Bitmap returnedBitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(),Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas (returnedBitmap);
Drawable bgDrawable =view.getBackground();
if (bgDrawable!=null) {
//has background drawable, then draw it on the canvas
bgDrawable.draw(canvas);
} else{
//does not have background drawable, then draw white background on the canvas
canvas.drawColor(Color.WHITE);
}
view.draw(canvas);
return returnedBitmap;
}
//Implementing Api using Retrofit
private void sendSceenShot(File file) {
RequestBody job=null;
Gson gson = new GsonBuilder ()
.setLenient ()
.create ();
Retrofit retrofit = new Retrofit.Builder ()
.baseUrl (BaseUrl.url)
.addConverterFactory (GsonConverterFactory.create (gson))
.build ();
final RequestBody requestBody = RequestBody.create (MediaType.parse ("image/*"),file);
job=RequestBody.create (MediaType.parse ("text"),jobId);
MultipartBody.Part fileToUpload = MultipartBody.Part.createFormData ("name",file.getName (), requestBody);
API service = retrofit.create (API.class);
Call<ScreenCapture_Pojo> call=service.sendScreen (job,fileToUpload);
call.enqueue (new Callback<ScreenCapture_Pojo> () {
#Override
public void onResponse(Call <ScreenCapture_Pojo> call, Response<ScreenCapture_Pojo> response) {
if (response.body ().getMessage ().equalsIgnoreCase ("Success")){
Toast.makeText (MapsActivity.this, "success", Toast.LENGTH_SHORT).show ();
}
}
#Override
public void onFailure(Call <ScreenCapture_Pojo> call, Throwable t) {
}
});
}
}
I hope this would help to capture the screenshot of your map
Method call:
gmap.setOnMapLoadedCallback(mapLoadedCallback);
Method declaration:
final SnapshotReadyCallback snapReadyCallback = new SnapshotReadyCallback() {
Bitmap bitmap;
#Override
public void onSnapshotReady(Bitmap snapshot) {
bitmap = snapshot;
try {
//do something with your snapshot
imageview.setImageBitmap(bitmap);
} catch (Exception e) {
e.printStackTrace();
}
}
};
GoogleMap.OnMapLoadedCallback mapLoadedCallback = new GoogleMap.OnMapLoadedCallback() {
#Override
public void onMapLoaded() {
gmap.snapshot(snapReadyCallback);
}
};
Eclipse DDMS can capture the screen even it's google map V2.
Try to call /system/bin/screencap or /system/bin/screenshot if you have the "root". I learned that from How Eclipse android DDMS implement "screen capture"

screenshot is blank on android

I'm taking a screenshot from a layout that have a videoview, I have this code to save it, and to capture it, but when I open it I have a blank image but not an empty the image have 1.5Kb, can you help me?
this is how I capture the screenshot
public void TakePic(View v){
buton = AnimationUtils.loadAnimation(this, R.anim.but);
v.startAnimation(buton);
if (vid!=null)
{
if(vid.getCurrentPosition()!=0)
{
popupc = (LinearLayout) findViewById(R.id.guardapic);
popupc.setVisibility(View.VISIBLE);
LinearLayout layout = (LinearLayout)findViewById(R.id.videopic);
layout.setDrawingCacheEnabled(true);
layout.setDrawingCacheQuality(LinearLayout.DRAWING_CACHE_QUALITY_HIGH);
layout.buildDrawingCache();
bitmap = layout.getDrawingCache();
im=(ImageView)findViewById(R.id.imgdown);
// im.setImageResource(R.drawable.play_amarelo);
im.setImageBitmap(bitmap);
}
else
{
Toast toast = Toast.makeText(ctx,"Video has stopped...Restart", Toast.LENGTH_SHORT);
toast.show();
}
}
else
{
Toast toast = Toast.makeText(ctx,"Start video first", Toast.LENGTH_SHORT);
toast.show();
}
}
this is the code to save it into the sdCard
public void PicOk(View v){
String pathpic=null;
String nomepic=null;
EditText path= (EditText)findViewById(R.id.picpath);
EditText pic= (EditText)findViewById(R.id.nomepic);
pathpic=path.getText().toString();
nomepic=pic.getText().toString();
File folder = new File(Environment.getExternalStorageDirectory() + "/"+pathpic);
boolean success = true;
if (!folder.exists()) {
success = folder.mkdir();
}
if (!success) {
Log.d("Lino"," Pasta nao criada");
} else {
FileOutputStream ostream;
try {
File file = new File(folder.toString() + "/"+nomepic+ ".png");
ostream = new FileOutputStream(file);
bitmap.compress(CompressFormat.PNG, 95, ostream);
ostream.flush();
ostream.close();
// ((LinearLayout)findViewById(R.id.VV2)).destroyDrawingCache();
} catch (FileNotFoundException e) {
Log.d("Lino","erro"+e.toString());
e.printStackTrace();
} catch (IOException e) {
Log.d("lino","erro "+e.toString());
e.printStackTrace();
}
}
popupc = (LinearLayout) findViewById(R.id.guardapic);
popupc.setVisibility(View.GONE);
bitmap=null;
//tira foto
Toast toast = Toast.makeText(ctx,"pick taked", Toast.LENGTH_SHORT);
toast.show();
}
You know the video is actually Combination of Still Images. The moment when you take the picture the cross-ponding frame is blank. That is why screenshot appears to be black/blank.
So with this method you can't take the screen shot of a video. You need to adopt a different approach.
May be it helps you.

how to take a screenshot?

I am taking a screenshot of a RelativeLayout but it cause the error.
error:
05-10 17:43:44.249: ERROR/AndroidRuntime(7721): Caused by: java.lang.NullPointerException
05-10 17:43:44.249: ERROR/AndroidRuntime(7721): at android.graphics.Bitmap.createBitmap(Bitmap.java:358)
05-10 17:43:44.249: ERROR/AndroidRuntime(7721): at com.API.Connect.share(FacebookConnect.java:110)
code:
public class Connect extends Activity implements LoginListener {
public static String news = " ";
RelativeLayout bitmapimage;
Bitmap bitmap;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.image);
bitmapimage = (RelativeLayout) findViewById(R.id.bitmapimg);
TextView txtlove = (TextView) findViewById(R.id.txtlove);
txtlove.setText(news.toString());
share();
}
public void share() {
View v1 = bitmapimage;
v1.setDrawingCacheEnabled(true);
bitmap = Bitmap.createBitmap(v1.getDrawingCache());
v1.setDrawingCacheEnabled(false);
saveImage();
// TODO Auto-generated method stub
}
void saveImage() {
String state = Environment.getExternalStorageState();
Environment.MEDIA_MOUNTED.equals(state);
File myDir = new File("/mnt/sdcard/DCIM/Camera");
myDir.mkdirs();
String fname = "mytry.jpg";
File file = new File(myDir, fname);
if (file.exists())
file.delete();
try {
FileOutputStream out = new FileOutputStream(file);
// create a Bitmap object from our image path.
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
What you are trying to do is correct. But in onCreate() your view wouldn't have drawn. It's just inflated. So you might have to consider using the below method. try this out.
#Override
public void onWindowFocusChanged(boolean hasFocus)
{
super.onWindowFocusChanged(hasFocus);
share(); //Call your share() here.
}
This method gets called once your view is drawn, and hence you will be able to get the bitmap by overriding this method.
I think i have found your error.
getdrawingcache already returns a bitmap, so you do not have to create a new one
that probably results into a nullpointer exception.
so you should try
bitmap = v1.getDrawingCache();
instead of
bitmap = Bitmap.createBitmap(v1.getDrawingCache());
let me know if this works.
Greets,
Wottah

Internal memory full of pictures, probably caused by Bitmap.compress(format, int, stream)

My app is a Wifi chat app with which you can communicate between two Android units with text messages and snap camera pictures and send them. The pictures are stored to the SD-card.
I used to have an OutOfMemoryError thrown after a couple of sent images, but I solved that problem by sending the
options.inPurgeable = true;
and
options.inInputShareable = true;
to the BitmapFactory.decodeByteArray method. This makes the pixels "deallocatable" so new images can use the memory. Thus, the error no longer remains.
But, the internal memory is still full of images and the "Low on space: Phone storage space is getting low" warning appears. The app no longer crashes but there's no more memory on the phone after the app finishes. I have to manually clear the app's data in Settings > Applications > Manage Applications.
I tried recycling the bitmaps and even tried to explicitly empty the app's cache, but it doesn't seem to do what i expect.
This function receives the picture via a TCP socket, writes it to the SD-card and starts my custom Activity PictureView:
public void receivePicture(String fileName) {
try {
int fileSize = inStream.readInt();
Log.d("","fileSize:"+fileSize);
byte[] tempArray = new byte[200];
byte[] pictureByteArray = new byte[fileSize];
path = Prefs.getPath(this) + "/" + fileName;
File pictureFile = new File(path);
try {
if( !pictureFile.exists() ) {
pictureFile.getParentFile().mkdirs();
pictureFile.createNewFile();
}
} catch (IOException e) { Log.d("", "Recievepic - Kunde inte skapa fil.", e); }
int lastRead = 0, totalRead = 0;
while(lastRead != -1) {
if(totalRead >= fileSize - 200) {
lastRead = inStream.read(tempArray, 0, fileSize - totalRead);
System.arraycopy(tempArray, 0, pictureByteArray, totalRead, lastRead);
totalRead += lastRead;
break;
}
lastRead = inStream.read(tempArray);
System.arraycopy(tempArray, 0, pictureByteArray, totalRead, lastRead);
totalRead += lastRead;
}
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(pictureFile));
bos.write(pictureByteArray, 0, totalRead);
bos.flush();
bos.close();
bos = null;
tempArray = null;
pictureByteArray = null;
setSentence("<"+fileName+">", READER);
Log.d("","path:"+path);
try {
startActivity(new Intent(this, PictureView.class).putExtra("path", path));
} catch(Exception e) { e.printStackTrace(); }
}
catch(IOException e) { Log.d("","IOException:"+e); }
catch(Exception e) { Log.d("","Exception:"+e); }
}
Here's PictureView. It creates a byte[ ] from the file on the SD-card, decodes the array to a Bitmap, compresses the Bitmap and writes it back to the SD-card. Lastly, in the Progress.onDismiss, the picture is set as the image of a full screen imageView:
public class PictureView extends Activity {
private String fileName;
private ProgressDialog progress;
public ImageView view;
#Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
Log.d("","onCreate() PictureView");
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
view = new ImageView(this);
setContentView(view);
progress = ProgressDialog.show(this, "", "Laddar bild...");
progress.setOnDismissListener(new OnDismissListener() {
public void onDismiss(DialogInterface dialog) {
File file_ = getFileStreamPath(fileName);
Log.d("","SETIMAGE");
Uri uri = Uri.parse(file_.toString());
view.setImageURI(uri);
}
});
new Thread() { public void run() {
String path = getIntent().getStringExtra("path");
Log.d("","path:"+path);
File pictureFile = new File(path);
if(!pictureFile.exists())
finish();
fileName = path.substring(path.lastIndexOf('/') + 1);
Log.d("","fileName:"+fileName);
byte[] pictureArray = new byte[(int)pictureFile.length()];
try {
DataInputStream dis = new DataInputStream( new BufferedInputStream(
new FileInputStream(pictureFile)) );
for(int i=0; i < pictureArray.length; i++)
pictureArray[i] = dis.readByte();
} catch(Exception e) { Log.d("",""+e); e.printStackTrace(); }
/**
* Passing these options to decodeByteArray makes the pixels deallocatable
* if the memory runs out.
*/
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPurgeable = true;
options.inInputShareable = true;
Bitmap pictureBM =
BitmapFactory.decodeByteArray(pictureArray, 0, pictureArray.length, options);
OutputStream out = null;
try {
out = openFileOutput(fileName, MODE_PRIVATE);
/**
* COMPRESS !!!!!
**/
pictureBM.compress(CompressFormat.PNG, 100, out);
pictureBM = null;
progress.dismiss(); }
catch (IOException e) { Log.e("test", "Failed to write bitmap", e); }
finally {
if (out != null)
try { out.close(); out = null; }
catch (IOException e) { }
} }
}.start();
}
#Override
protected void onStop() {
super.onStop();
Log.d("","ONSTOP()");
Drawable oldDrawable = view.getDrawable();
if( oldDrawable != null) {
((BitmapDrawable)oldDrawable).getBitmap().recycle();
oldDrawable = null;
Log.d("","recycle");
}
Editor editor =
this.getSharedPreferences("clear_cache", Context.MODE_PRIVATE).edit();
editor.clear();
editor.commit();
}
}
When the user presses the back key, the picture isn't supposed to be available anymore from within the app. Just stored on the SD-card.
In onStop() I recycle the old Bitmap and even try to empty the app's data. Still the "Low on space" warning appears. How can I be sure the images won't allocate the memory anymore when they're not needed?
EDIT: It appears the problem is the compress method. If everything after compress is commented, the problem remains. If I delete compress, the problem disappears. Compress seems to allocate memory that's never released, and it's 2-3 MB per image.
Ok, I solved it. The problem was, I was passing an OutputStream to compress, which is a stream to a private file in the app's internal memory. That's what I set as the image later. This file is never allocated.
I didn't get that I had two files: one on the SD-card and one in the internal memory, both with the same name.
Now, I'm just setting the SD-card file as the ImageView's image. I never read the file into the internal memory as a byte[], thus never decoding the array to a bitmap, thus never compressing the bitmap into the internal memory.
This is the new PictureView:
public class PictureView extends Activity {
public ImageView view;
private String path;
#Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
Log.d("","onCreate() PictureView");
path = getIntent().getStringExtra("path");
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
view = new ImageView(this);
setContentView(view);
Uri uri = Uri.parse( new File(path).toString() );
view.setImageURI(uri);
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
Log.d("","Back key pressed");
Drawable oldDrawable = view.getDrawable();
if( oldDrawable != null) {
((BitmapDrawable)oldDrawable).getBitmap().recycle();
oldDrawable = null;
Log.d("","recycle");
}
view = null;
}
return super.onKeyDown(keyCode, event);
}
}
Is it bad practice to put an external file as the image of an ImageView? Should I load it into internal memory first?
If you specifically want the image to be nullified from memory for sure when a user presses back you could override the back button and make your image clean up calls there. I do that in some of my apps and it seems to work. maybe something like this:
#Override
protected void onBackPressed() {
super.onBackPressed();
view.drawable = null;
jumpBackToPreviousActivity();
}
Im pretty sure there are some view methods that clear other caches and things like that. You can recycle the bitmap but that doesnt guarantee that it will be dumped right then but only at some point when the gc gets to it.....but Im sure you probably know that already :)
EDIT: You could also do the same thing in the onPause method. That one is guaranteed to get called. The other two may never get called according to the android docs.
http://developer.android.com/reference/android/app/Activity.html

Categories

Resources