I am pretty new to Android development and I'm trying to figure out how to tap an image in my app and save it to the device. When the image is tapped I want a Save button to appear and when that is pressed, a toast should appear saying the picture was saved. On iOS I am able to do this with UIActionSheet.
I should also mention that the image view image is downloaded from a URL using Picasso.
I just tried this and it says the image saved but when I go to the photos app on my phone, the image is not there.
largeImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
saveButton.setVisibility(View.VISIBLE);
}
});
saveButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
largeImage.getDrawable();
Bitmap bitmap = ((BitmapDrawable)largeImage.getDrawable()).getBitmap();
OutputStream outStream = null;
File file = new File(storageDirectory, "er.PNG");
try {
outStream = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, outStream);
outStream.flush();
outStream.close();
Toast.makeText(FlickrImageActivity.this, "Saved", Toast.LENGTH_LONG).show();
}
catch (FileNotFoundException e) {
e.printStackTrace();
Toast.makeText(FlickrImageActivity.this, e.toString(), Toast.LENGTH_LONG).show();
}
catch (IOException e) {
e.printStackTrace();
Toast.makeText(FlickrImageActivity.this, e.toString(), Toast.LENGTH_LONG).show();
}
saveButton.setVisibility(View.GONE);
}
});
String root = Environment.getExternalStorageDirectory().toString();
File myDir = new File(root + "/saved_images");
myDir.mkdirs();
Random generator = new Random();
int n = 10000;
n = generator.nextInt(n);
String fname = "Image-"+ n +".jpg";
File file = new File (myDir, fname);
if (file.exists ()) file.delete ();
try {
FileOutputStream out = new FileOutputStream(file);
finalBitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
Manifest permission
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
You can use RelativeLayout to contain a ImageView and a Button.
Align both of them center in parent
inside the activity, set the button visibility to "gone"
call setOnClickListener of the ImageView and Button to your Activity
implement OnClickListener in your Activity
inside onClick(View v), if the view clicked is the ImageView, set the visibility of Button to "visible"
inside onClick(View v), if the view clicked is the Button, save the image to disk
** how to save image to disk
if the image source is drawable resources, use BitmapFactory.decodeResource to create a Bitmap then use Bitmap.compress to export to a specific path
specific path is recommended to be obtained from Environment.getExternalStoragePublicDirectory
then notify the Android to refresh gallery
MediaScannerConnection.scanFile(context,
new String[] { imagePath }, null,
new MediaScannerConnection.OnScanCompletedListener() {
#Override
public void onScanCompleted(String path, Uri uri) {
//....
}
});
Then use a Toast.makeText(context, "message here").show(); to show the message to user
See below steps to acheive this in Android :
1. Create layout with ImageView & 'Save' named Button
2.By deafult set 'Save' Button's visibility = gone/invisible
3. Apply click listener on both the views (ImageView & Button)
4. OnClick of ImageView, set 'Save' Button's visibility = visible
5. onclick of save button click call your save image to sdcard logic. Check below link for that.
http://android-er.blogspot.in/2010/07/save-file-to-sd-card.html
Hope this will help you.
Related
So, I'm (still) trying to build a simple camera app and what I have so far is an Image Controller which is able to take a picture, save it into the storage and pass the filepath with an intent to another activity.
In my new activity the first step I'm tying to achieve is, to get my final Image loaded into an ImageView, so I did the following:
ImageView finalImage;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_after);
Intent getIntent = getIntent();
String filePath = getIntent.getExtras().getString("filePath");
File imgFile = new File(filePath);
if(imgFile.exists()){
Bitmap myBitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath());
finalImage = (ImageView) findViewById(R.id.finalImage);
finalImage.setImageBitmap(myBitmap);
}
But, its not working, and I dont quite unterstand why not... :( The Activity starts completely fine, but the ImageView just does nothing.
There are few things you must know in the process of saving Image in Android
ccv2WithPreview.takePicture();
In this line the method executed is
public void takePicture() {
try {
// This is how to tell the camera to lock focus.
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_START);
// Tell #mCaptureCallback to wait for the lock.
mState = STATE_WAITING_LOCK;
mCaptureSession.capture(mPreviewRequestBuilder.build(), mCaptureCallback, backgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
Toast.makeText(activity.getApplicationContext(), file.getAbsolutePath(), Toast.LENGTH_SHORT).show();
}
In this method, capture() call is asynchronous. Since you are ending the activity soon after calling it and starting new Activity, so by the time your code saves the Image in Image Saver, you are starting new Activity already and your file is not yet ready.
You button implementation works because by the time you click button, Image will be saved.
To solve this problem,
CameraHelper.java
public interface CameraHelper{
void fileSaved(String filePath);
}
MainActivity.java
public class MainActivity extends AppCompatActivity
implements SensorEventListener, ActivityCompat.OnRequestPermissionsResultCallback, CameraHelper{
...
#Override
public void fileSaved(String file){
Intent intent = new Intent(this, AfterActivity.class);
intent.putExtra("filePath", file);
startActivity(intent);
finish();
}
}
in onCreate of MainActivity
ccv2WithPreview = new CameraControllerV2WithPreview(MainActivity.this, textureView, MainActivity.this);
in your camera class
private CameraHelper cameraHelper; //Initialize in constructor
Then in ImageSaver
private boolean imageSaved = false;
public void run() {
if(!imageSaved) {
ByteBuffer buffer = mImage.getPlanes()[0].getBuffer();
byte[] bytes = new byte[buffer.remaining()];
buffer.get(bytes);
try (FileOutputStream output = new FileOutputStream(mFile)) {
output.write(bytes);
imageSaved = true;
cameraHelper.fileSaved(mFile.getAbsolutePath());
} catch (IOException e) {
e.printStackTrace();
} finally {
mImage.close();
}
}
}
This is how you must handle any Asynchronous tasks you get in future. Callback based implementations.
Can you try to invalidate() the ImageView after setting the bitmap?
(I'm pretty much guessing here, but working with GUIs a couple of years ago, i remember that if a view changed you have to tell the view to about it, so that it can be redrawn.)
Please also see: How to refresh image view immediately
I am creating a button dynamically in Android Studio in a class that extends Fragment. I have my button created (btn) and a text that I want to go under that button (appName), but now I want to place the button next to another button that already exists (lets call it btn_2). I am having trouble finding out how to place one widget next to another using Java, and not xml. Here is what I have so far:
public void createButton (BitmapDrawable bitmapdrawable, String applicationName){
LayoutInflater inflater=null;
ViewGroup container = null;
// Get Layout home_fragment
View rootView = inflater.inflate(R.layout.home_fragment, container, false);
RelativeLayout rLayout = (RelativeLayout) rootView.findViewById(R.id.home_fragment);
// create image button with background as bitmapdrawable
ImageButton btn = new ImageButton(getActivity());
btn.setImageDrawable(bitmapdrawable);
// create textview with applicationName
TextView appName = new TextView(getActivity());
appName.setText(applicationName);
// place new button next to existing button
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.RIGHT_OF);
btn.setLayoutParams(params);
// place text under newly created button
// Put button and text in layout
rLayout.addView(btn);
rLayout.addView(appName);
}
Where I am running into errors is:
params.addRule(RelativeLayout.RIGHT_OF);
How do I pass through the ID of the EXISTING button (btn_2), that I want my new button (btn) to be placed next to?
Then, I want to fill in this empty gap
// place text under newly created button
of how to place my newly created textview (appName) under my newly created btn and under my existing btn_2. (Maybe this will be more straight forward after I figure out how to place one button next to the other.)
Here is my MainActivity. My image and string that I am passing to HomeFragment createButton method are being sent to MainActivity through a socket from another device:
// main activity (FragmentActivity provides fragment compatibility pre-HC)
public class MainActivity extends FragmentActivity implements MenuFragment.OnMenufragListener {
private Thread repeatTaskThread;
private byte[] byteArray;
// called when the activity is first created
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Listening for last installed app to create button
RepeatTask();
}
#Override
public void onMenufrag(Fragment s) {
// get body fragment (native method is getFragmentManager)
HomeFragment fragment = (HomeFragment) getSupportFragmentManager().findFragmentById(R.id.home_fragment);
// if fragment is not null and in layout, set text, else launch BodyActivity
if ((fragment!=null)&&fragment.isInLayout()) {
fragment.getView();
} else {
Intent intent = new Intent(this,HomeFragment.class);
startActivity(intent);
}
}
private void RepeatTask()
{
repeatTaskThread = new Thread()
{
public void run()
{
while (true)
{
try {
System.out.println("TRY_1");
Socket socket = new Socket("192.168.0.26", 5050);
// Get data sent through socket
DataInputStream DIS = new DataInputStream(socket.getInputStream());
System.out.println("DataInputStream Started");
// read data that got sent
String applicationName = DIS.readUTF();
// read array data for bitmap
//Drawable icon = getPackageManager().getApplicationIcon(packagename);
//System.out.println("icon" + icon);
int len = DIS.readInt();
byte[] data = new byte[len];
DIS.readFully(data, 0, data.length);
// Convert data to jpeg first then to bitmap (cant convert byte array directly to bitmap)
YuvImage yuvimage=new YuvImage(data, ImageFormat.NV21, 100, 100, null);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
yuvimage.compressToJpeg(new Rect(0, 0, 100, 100), 80, baos);
byte[] jdata = baos.toByteArray();
// Convert to Bitmap
Bitmap bmp = BitmapFactory.decodeByteArray(jdata, 0, jdata.length);
// Image to png in file directory
// STREAM IMAGE DATA TO FILE
// This is how I know I am correctly getting my png image (no errors here)
// convert bitmap to drawable
Drawable d = new BitmapDrawable(getResources(), bmp);
// convert drawable to bitmapdrawable
BitmapDrawable bitmapdrawable = (BitmapDrawable)d;
Log.d("tag_name", "BITMAP Drawable" + bitmapdrawable);
// Create file to stream bitmpadrawable
FileOutputStream fosIcon = openFileOutput(applicationName + ".png", Context.MODE_PRIVATE);
// compress bitmapdrawable into png and write to file that was just created
bitmapdrawable.getBitmap().compress(Bitmap.CompressFormat.PNG, 100, fosIcon);
InputStream inputStream = openFileInput(applicationName + ".png");
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
// GET FILE DIRECTORY
File imageFile = new File(getFilesDir(), applicationName + ".png");
HomeFragment createbutton = new HomeFragment();
createbutton.createButton(bitmapdrawable, applicationName);
Log.d("tag_name", "Entered Home Fragment");
socket.close();
} catch (Exception e) {
System.out.println("Exception is "+e.toString());
}
try
{
// Sleep for 5 seconds
Thread.sleep(5000);
}
catch (Exception e)
{
e.printStackTrace();
}
}
};
};
repeatTaskThread.start();
}
}
Here is my xml for HomeFragment:
<?xml version="1.0" encoding="utf-8"?>
<HorizontalScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:layout_margin="5dp"
android:id="#+id/home_fragment"
>
</RelativeLayout>
</HorizontalScrollView>
You have to specify the view id to make your view right of . Try -
TextView appName = new TextView(getActivity());
int id = 1001;
appName.setId(id);
params.addRule(RelativeLayout.RIGHT_OF, id);
I'm creating an app to open a PDF application from a button, but what I did is not going well.
In my layout there is only one button , which seeks want and open a PDF file.
Not giving error in Eclipse , just in tablet appears " readerPDF stopped ."
I do not know what to do. somebody help me.
Sorry for my english.
public class ReaderActivity extends Activity {
private Button btnOpen;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_reader);
btnOpen.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
String filename = null;
File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() +"/"+ filename);
Intent target = new Intent(Intent.ACTION_VIEW);
target.setDataAndType(Uri.fromFile(file),"application/pdf");
target.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
Intent intent = Intent.createChooser(target, "Open File");
try {
startActivity(intent);
} catch (ActivityNotFoundException e) {
}
}
});
}
}
filename is null, so the path you are passing to the third-party app does not point to a PDF file.
how to make users to download the image in the listview onclick of the list item.The images are from drawable folder, not from the web?
if you are referring to saving images to your phone, from your drawable folder.you should check this link out.
How to save a bitmap image with imageview onclick
it says how to save an image from the app to your phone
To get bitmap from imageview:
imageview.buildDrawingCache();
Bitmap bm=imageview.getDrawingCache();
To save it in a file:
OutputStream fOut = null;
Uri outputFileUri;
try {
File root = new File(Environment.getExternalStorageDirectory() + File.separator + "folder_name" + File.separator);
root.mkdirs();
File sdImageMainDirectory = new File(root, "myPicName.jpg");
outputFileUri = Uri.fromFile(sdImageMainDirectory);
fOut = new FileOutputStream(sdImageMainDirectory);
} catch (Exception e) {
Toast.makeText(this, "Error occured. Please try again later.",
Toast.LENGTH_SHORT).show();
}
try {
bm.compress(Bitmap.CompressFormat.PNG, 100, fOut);
fOut.flush();
fOut.close();
} catch (Exception e) {
}
give this inside the listview on click
You can store your images id in an int[] integer array like this:
int[] myImages = {R.drawable.myfirstimage,R.drawable.mysecondimage};
and add to your listView an onItemClick method where you change your corresponding ImageView based on the position of the item clicked
myListview.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
ImageView imageView = (ImageView) view.findViewById(R.id.myImageView);
imageView.setBackgroundResource(myImages[position]);
}
});
I want to change the visibility of a view from GONE to VISIBLE and take a screenshot of my whole application and save it in a file.
I'm able to take the screenshot, but the view remain not visible (GONE) in the jpeg file. The method is called from a button click:
public void onClick(View v) {
View screen = (View) findViewById(R.id.mainLayout);
//I change this from View.GONE
TextView hiddenText = (TextView) findViewById(R.id.hiddenText);
hiddenText.setVisibility(View.VISIBLE);
hiddenText.setText( "WEEEEEEEEEE" + (int)(Math.random()*10) );
View rootview = screen.getRootView();
//View rootview = getWindow().getDecorView().getRootView();
rootview.invalidate(); //I try to redraw the view without success
rootview.requestLayout();
rootview.setDrawingCacheEnabled(true);
Bitmap bitmap = rootview.getDrawingCache();
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 40, bytes);
String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) +
File.separator + "Facebook" + File.separator + "my_screenshot.jpeg";
File file = new File(path);
file.getParentFile().mkdirs(); //if the folder doesn't exists it's created
try {
boolean asd = file.createNewFile();
FileOutputStream ostream = new FileOutputStream(file);
ostream.write(bytes.toByteArray());
ostream.close();
}
catch (Exception e){
e.printStackTrace();
}
//hiddenText.setVisibility(View.GONE);
}
After that I save the file I should hide again the TextView hiddenText, but I doesn't know in which point to set the visibility GONE.