I'm building a profile page for my app. I've made it in such a way that tapping on the previous profile image, the user will be able to change its profile picture. I would like that after the upload, the profile picture will be instantaneously updated. I've tried using Picasso but it seems to have some problems with the cache. In fact after the user has chosen his image, the picture which is shown is the same as before, despite the fact that the app overwrites the previous image file and re-apply Picasso. I'm using Android API 22.
Profile.java
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.profile);
ImageView pic = (ImageView) findViewById(R.id.picc);
...
String root = Environment.getExternalStorageDirectory().toString();
String path = root + "/directory/name.jpg";
MainActivity.trimCache(this);
Picasso.with(getApplicationContext()).load(path)
.networkPolicy(NetworkPolicy.NO_CACHE)
.memoryPolicy(MemoryPolicy.NO_CACHE)
.transform(new RoundedTransformation(1000, 0))
.resize(500, 500)
.centerCrop()
.into(pic);
}
pic.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent chooseImageIntent = ImagePicker.getPickImageIntent(getApplicationContext());
startActivityForResult(chooseImageIntent, PICK_IMAGE_ID);
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Bitmap bitmap = ImagePicker.getImageFromResult(this, resultCode, data);
ImageView pic = (ImageView) findViewById(R.id.picc);
RetrieveFeedTask job = new RetrieveFeedTask(data, resultCode, this, bitmap);
job.execute("user","pass");
String root = Environment.getExternalStorageDirectory().toString();
String path = root + "/directory/name.jpg";
MainActivity.trimCache(this);
Picasso.with(getApplicationContext()).load(path)
.networkPolicy(NetworkPolicy.NO_CACHE)
.memoryPolicy(MemoryPolicy.NO_CACHE)
.transform(new RoundedTransformation(1000, 0))
.resize(500, 500)
.centerCrop()
.into(pic);
}
ImagePicker.java is a standard image picker file.
I've also tried to delete the cache from the app with the following function
public static void trimCache(Context context) {
try {
File dir = context.getCacheDir();
if (dir != null && dir.isDirectory()) {
deleteDir(dir);
}
} catch (Exception e) {
// TODO: handle exception
}
}
The Picasso instance, by default, holds a memory cache. Picasso sees the same key for the cache (the path in this case) and just simply returns the Bitmap instance from the cache that it gets from that key.
You have the right thing there with memoryPolicy(MemoryPolicy.NO_CACHE) to skip the cache check; are you sure that's the way you are calling for the image after the change/update?
Related
My app displays a customed list of videos with the option to download using IntentService. The custom list is displayed on the UI using a recyclerView system. Below is a pic of the list
When a video is clicked and downloaded, the download icon turns blue as seen in the first child of the list shown in the picture above and when it has not been downloaded it shows the default black download icon. I have strung up some codes to make it work, the challenge is, when the app is restarted, The download icon revert to its default color even when it was previously downloaded. How do I update and save changes made to the color of the download icon so it will reflect when the app is restarted? I understand the SharedPreference class can be used to save changes made to the App, but I don't know how to achieve this. Would appreciate any assist that can be lent to achieve this
Below is my onCreate mtd
#Override
protected void onCreate(Bundle savedInstanceState) {
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_lecture);
setUpRecyclerView();
And below is where I created the setUpRecyclerView()
private void setUpRecyclerView() {
Query query = lectureRef.orderBy("position", Query.Direction.ASCENDING);
FirestoreRecyclerOptions<LectureClasses> options = new FirestoreRecyclerOptions.Builder<LectureClasses>()
.setQuery(query, LectureClasses.class).build();
adapter = new LectureClassesAdapter(options);
recyclerView = findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(adapter);
}
Below is my call of the onViewItemclick #overide method setup in my adapter class
#Override
public void onViewItemClick(DocumentSnapshot snapshot, int position, View itemView) {
//init variables
CircularProgressBar progressBarCir = itemView.findViewById(R.id.progress_circular);
progressBarCir.setProgressMax(100f);
ImageView downloadImage = itemView.findViewById(R.id.download);
PopupMenu popupMenu = new PopupMenu(LectureActivity.this,downloadImage);
LectureClasses lectureClasses = snapshot.toObject(LectureClasses.class);
lectureClasses = adapter.getItem(position);
String titleNow = lectureClasses.getTitle();
String urlNow = lectureClasses.getUrl();
class DownloadReceiver extends ResultReceiver {
public DownloadReceiver(Handler handler) {
super(handler);
}
#Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
super.onReceiveResult(resultCode, resultData);
if (resultCode == TichaDownloadService.UPDATE_PROGRESS) {
int progress = resultData.getInt("progress");
progressBarCir.setProgress(progress);
downloadImage.setVisibility(View.GONE);
progressBarCir.setVisibility(View.VISIBLE);
Log.i("STATUS","DOWNLOADING>>>");
if (progress == 100) {
progressBarCir.setVisibility(View.GONE);
downloadImage.setImageDrawable(getDrawable(R.drawable.download_blue));
downloadImage.setVisibility(View.VISIBLE);
}
}else {
Log.i("STATUS"," NOT DOWNLOADING,BOSS");
}
}
}
}
you are can to check the file with below code
File videoFile = new File("patch_video_file");
if (videoFile.exists()){
// visible button blue
}else {
// visible button default
}
This question already has answers here:
How to manage startActivityForResult on Android
(14 answers)
Closed 3 years ago.
I am using both an ImagePicker and a barcode reader in a single activity. The main problem is that both of these require onActivityResult() to display the result. As we know a single activity can only have a single onActivityResult() method in it. How can I display both of them?
I have tried using switch cases to assign multiple requestCodes in the onActivityResult() but can't seem to figure out the solution.
Here's the method I tried.
public class MainActivity extends AppCompatActivity{
private TextView mIdentificationNumber;
private IntentIntegrator scanQR;
//Authentication For Firebase.
private FirebaseAuth mAuth;
//Toolbar
private Toolbar mToolBar;
private DatabaseReference mUserRef;
private ImageView mAssetImg;
private EditText massetName, massetModel, massetBarcode, massetArea, massetDescription;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Getting the Present instance of the FireBase Authentication
mAuth = FirebaseAuth.getInstance();
//Finding The Toolbar with it's unique Id.
mToolBar = (Toolbar) findViewById(R.id.main_page_toolbar);
//Setting Up the ToolBar in The ActionBar.
setSupportActionBar(mToolBar);
if (mAuth.getCurrentUser() != null){
mUserRef = FirebaseDatabase.getInstance().getReference().child("Users")
.child(mAuth.getCurrentUser().getUid());
mUserRef.keepSynced(true);
}
massetBarcode = (EditText) findViewById(R.id.BarcodeAsset);
scanQR = new IntentIntegrator(this);
massetBarcode.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
scanQR.initiateScan();
}
});
mAssetImg = (ImageView) findViewById(R.id.asset_img);
mAssetImg.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getImage();
}
});
}
//OnStart Method is started when the Authentication Starts.
#Override
public void onStart() {
super.onStart();
// Check if user is signed in (non-null).
FirebaseUser currentUser = mAuth.getCurrentUser();
if (currentUser == null){
startUser();
} else {
mUserRef.child("online").setValue("true");
Log.d("STARTING THE ACTIVITY" , "TRUE");
}
}
#Override
protected void onPause() {
super.onPause();
FirebaseUser currentUser = mAuth.getCurrentUser();
if (currentUser != null){
mUserRef.child("online").setValue(ServerValue.TIMESTAMP);
Log.d("STOPPING THE ACTIVITY" , "TRUE");
}
}
private void startUser() {
//Sending the user in the StartActivity If the User Is Not Logged In.
Intent startIntent = new Intent(MainActivity.this , AuthenticationActivity.class);
startActivity(startIntent);
//Finishing Up The Intent So the User Can't Go Back To MainActivity Without LoggingIn.
finish();
}
//Setting The Menu Options In The AppBarLayout.
#Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
//Inflating the Menu with the Unique R.menu.Id.
getMenuInflater().inflate(R.menu.main_menu , menu);
return true;
}
//Setting the Individual Item In The Menu.(Logout Button)
#Override
public boolean onOptionsItemSelected(MenuItem item) {
super.onOptionsItemSelected(item);
if (item.getItemId() == R.id.main_logout_btn){
FirebaseAuth.getInstance().signOut();
startUser();
}
return true;
}
private void getImage() {
ImagePicker.Companion.with(this)
.crop() //Crop image(Optional), Check Customization for more option
.compress(1024) //Final image size will be less than 1 MB(Optional)
.maxResultSize(1080, 1080) //Final image resolution will be less than 1080 x 1080(Optional)
.start();
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case 0:
IntentResult result = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
if (result != null) {
if (result.getContents() == null) {
Toast.makeText(this, "Cancelled", Toast.LENGTH_LONG).show();
} else {
massetBarcode.setText(result.getContents());
Toast.makeText(this, "Scanned: " + result.getContents(), Toast.LENGTH_LONG).show();
}
}
break;
case 1:
if (resultCode == Activity.RESULT_OK) {
assert data != null;
Uri imageURI = data.getData();
mAssetImg.setImageURI(imageURI);
}
break;
}
}
}
The rest of the answers told to use startActivityForResult() but that method requires Intent to go from one activity to another but I don't want to do this.
In both cases, the libraries you're using provide a way to specify a request code so you can distinguish the results in onActivityResult.
Your scanQR object should set a request code, per the source code:
massetBarcode.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
scanQR.setRequestCode(123).initiateScan();
}
});
You getImage() method should also specify a request code, again, per the library's source code.
private void getImage() {
ImagePicker.Companion.with(this)
.crop() //Crop image(Optional), Check Customization for more option
.compress(1024) //Final image size will be less than 1 MB(Optional)
.maxResultSize(1080, 1080) //Final image resolution will be less than 1080 x 1080(Optional)
.start(456); // Start with request code
}
Now, you can handle each request code as needed:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case 123:
// HANDLE BARCODE
break;
case 456:
// HANDLE IMAGE
break;
}
}
Closing thought: I've never used either library. I found the solution by 1) assuming any library that provides an Activity you're supposed to invoke for a result would allow you to specify a request code for it and 2) looking through their documentation and source code for how to do that.
I'd encourage you to thoroughly study the documentation and source code for any open source library you intend to use since as soon as you do their code become your code and their bugs become your bugs, so you better know how to fix or workaround them.
Hope that helps!
In order to get results from fragments to your Activity, you can use an Interface to enable communication between them.
StartActivityForResult is used to start an activity and get a result back from it.
Please read more about it from here.
The startActivityForResult methos can use a second argument, a number so you can distinguish the resul
startActivityForResul(intent, 8)
You dont need to set the code back in the other activity, that is handled under the hood. So you probabbly want to add the number as a contant
private static final CAMERA_INTENT = 2
And then use it like this
startActivityForResul(intent, CAMERA_INTENT)
Finally in the onActivityResult implements the case basis
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
if (CAMERA_INTENT == requestCode) {
//DO PHOTO STUFF
}
}
The argument you need to eval is requestCode
I created a list view that uploads files from sd card to and attaches it within the list. Yet I back out of the activity and onDestroyed gets called and I lose all my data from my listView. I am using An ArrayList FileUploaded and adapter to upload the files but I am confused on how I can implement that on "onSavedInstanceState" method.
I've done research but I am still having some issues.
Am I storing the wrong Items?
Please help... any advice at all.
My Variables:
ListView Added_Files;
Button Select_File;
Button Add_To_List;
Button Save_Button;
Button Add_To_DropBox;
TextView selectedFile;
MediaPlayer mediaPlayer;
ArrayList<Uri> FileUpload = new ArrayList<Uri>();
ArrayAdapter adapter;
//method that adds the file to listView when button "Upload to List" is clicked
public void addList(){
adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1,FileUpload);
Add_To_List.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Added_Files.setAdapter(adapter);
adapter.add(uri.getPath());
((BaseAdapter) Added_Files.getAdapter()).notifyDataSetChanged();
selectedFile.setText("");
Make_File_Empty();
// Toast.makeText(AddFiles.this, "File Added", Toast.LENGTH_SHORT).show();
}
});
}
Here is the method when file on sd card is selected and displays it on the screen
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQUEST_CODE:
//If file selection was successfull
if (resultCode == RESULT_OK) {
if (data != null) {
//get uri of the selected file
uri = data.getData();
Log.i(TAG, "Uri = " + uri.toString());
try {
//get file path from Uri
// Toast.makeText(AddFiles.this, "File Selected: " + uri.getPath(), Toast.LENGTH_SHORT).show();
selectedFile.setText("Selected File: " + uri.getPath());
addList();
} catch (Exception e) {
Log.e("FileSelectorActivity", "File select error", e);
}
super.onActivityResult(requestCode, resultCode, data);
}
}
}
}
Lastly, the onSaved/restore methods:
#Override
public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
super.onSaveInstanceState(outState, outPersistentState);
outState.putStringArrayList("key",FileUpload );
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
FileUpload = savedInstanceState.getStringArrayList("key");
}
Take a careful look at this article: https://developer.android.com/guide/components/activities/activity-lifecycle#save-simple-lightweight-ui-state-using-onsaveinstancestate
It looks like in onSaveInstanceState you're saving your state after calling super, which might cause the data to not get saved. You also might want to save and restore the text in your TextView so it's shown when the UI is restored.
Another thing to note is what it says here:Note: onSaveInstanceState() is not called when the user explicitly closes the activity or in other cases when finish()is called.
Saving state is only intended to save data in short term situations (the example saves it before calling super), if you want to save it for longer (between app launches) you might want to use a SQLite database which is a lot more complicated.
I'm not an expert at this stuff specifically but hope this helped! I'd recommend setting breakpoints in onSaveInstanceState and onRestoreInstanceState to see what is being called when if you're still having trouble.
I have a problem with my camera app, which is that when I take a photo I can see it in the imageview, but when I turn my phone or close the app and reopen it, the image disappears.
My code->
public class semana1 extends Activity {
Button btnfoto1;
ImageView imgs1;
static final int CAM_REQUEST=1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.semana1);
btnfoto1= (Button) findViewById(R.id.btnfoto1);
imgs1= (ImageView) findViewById(R.id.imgs1);
btnfoto1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent int1=new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File file=getfile();
int1.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));
startActivityForResult(int1,CAM_REQUEST);
}
});
}
private File getFile()
{
File folder=new File("sdcard/Progress");
if(!folder.exists())
{
folder.mkdir();
}
File image_file=new File(folder,"image1.jpg");
return image_file;
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
String path = "sdcard/Progress/image1.jpg";
imgs1.setImageDrawable(Drawable.createFromPath(path));
}
}
Read up on the activity lifecycle of an app.
Now to point you in somewhat the right direction. When you close your app, the system stops the app and might later kill it. The reason why your image disappears is because you haven implemented a way for your app to save the state it was in before hand.
Therefore, you should probably implement:
public void onStop() {
super.onStop();
// code where you tell the app to save the image
}
public void onDestroy() {
super.onDestroy();
// code where you tell the app to save the image
}
I am working on camera related app in android. What I want is when user takes photo he should be immediately take to previous activity where he was before. Right now what my code does is when user takes a photo then two button appear at the bottom of the screen i.e. Save and Discard. So I do not want that. When the picture is taken user should be directly navigate to previous activity. How can acheive this?
Here is my code
public class CameraActivity extends Activity implements View.OnClickListener {
ImageView iv;
Button bCapture, bSetWall;
Intent i;
int CameraResult = 0;
Bitmap bmp;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
initialize();
InputStream is = getResources().openRawResource(R.drawable.ic_launcher);
bmp = BitmapFactory.decodeStream(is);
}
private void initialize() {
iv = (ImageView)findViewById(R.id.ivCamera);
bCapture = (Button)findViewById(R.id.bCapture);
bSetWall = (Button)findViewById(R.id.bSetWall);
bCapture.setOnClickListener(this);
bSetWall.setOnClickListener(this);
}
public void onClick(View v) {
switch(v.getId()) {
case R.id.bCapture:
i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(i, CameraResult);
break;
case R.id.bSetWall:
try {
getApplicationContext().setWallpaper(bmp);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
super.onActivityResult(requestCode, resultCode, data);
if(resultCode == RESULT_OK) {
Bundle extras = data.getExtras();
bmp = (Bitmap) extras.get("data");
iv.setImageBitmap(bmp);
}
}
}
The code you have right now will capture photos using an existing camera application. That is, it is making use of an already existing Activity that belongs to some camera application that is installed on your device.
That said, there is no way to manipulate Activitys that belong to other applications. You'll have to implement your own Camera Activity instead.