I've created a test app to understand how to call the native gallery, select an image and display it on an imageView.
1st test
I had a simple setup. One activity and a fragment(residing within that activity) that has a button(calls gallery intent) and an imageView for the selected image. This worked perfectly.
2nd test
Changed the setup a bit by adding another activity and a tab host to the main activity. This new empty activity would be the launching activity and it's only purpose was to switch to the main activity that holds the fragment that calls the gallery intent. Everything works fine until I select the image from the gallery. Once the image is selected, it doesn't go back to the my test app. It's like a weird soft crash. Logcat doesn't display any errors so it's a bit hard to troubleshoot. I also placed a breakpoint on each line of the OnActivityResult override but they never hit.
I was hoping somebody would shed light on this matter.
SDK version is 23 and build tools is 23.0.3
Heres what I got so far:
Main2Activity(Launching activity)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
ActivityConfig.CreateActivity(MainActivity.class, this, true);
}
In case you were wondering what CreateActivity does:
public static void CreateActivity(Class activityClass, Context context,
boolean finishPreviousActivity)
{
Intent intent = new Intent(context, activityClass);
if (finishPreviousActivity)
{
intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
}
context.startActivity(intent);
}
MainActivity(I only use the third position on the tabhost. That's where the fragment is)
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TabHost tabHost = (TabHost) findViewById(R.id.tabHost);
tabHost.setup();
tabHost.addTab(Tabs.CreateTab("T1", R.id.tabFrag2, tabHost));
tabHost.addTab(Tabs.CreateTab("T2", R.id.tabFrag3, tabHost));
tabHost.addTab(Tabs.CreateTab("T3", R.id.tabFrag, tabHost));
tabHost.setCurrentTab(2);
}
Fragment
private ImageView imageView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.fragment_blank, container, false);
Button button = (Button)view.findViewById(R.id.Btn);
imageView = (ImageView)view.findViewById(R.id.Img);
button.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.INTERNAL_CONTENT_URI);
intent.setType("image/*");
startActivityForResult(intent, 100);
}
});
return view;
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 100)
imageView.setImageURI(data.getData());
}
After much trail an error I noticed that after selecting an image it was going back to the launching activity, but not through onCreate or it's overridden onActivityResult. It was going through onResult. My conclusion was redesign the whole interface in a way that only one activity was required
Related
So far in my social media app, the user's data such as first name, last name, email, gender, and more can be saved in a firebase database and retrieved when needed. As of today, I got a working profile picture when first creating a profile you can tap on the empty profile picture icon and it loads up your gallery replacing it with whatever image the user chooses.
Although this is quite neat I need to be able to upload this image somehow under the Users node in my firebase database. I am quite lost when it comes to converting the bitmap data and after reading through some documentation it still confuses me. Below is my code for using a locally saved photo replacing it as the profile picture to show what I have so far.
#Override
public void onClick(View view)
{
if (view == profilePicture)
{
//Toast.makeText(this, "We made it to the onClick for image!", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, 0);
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK)
{
Uri targetUri = data.getData();
Bitmap bitmap;
try
{
bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(targetUri));
profilePicture.setImageBitmap(bitmap);
}
catch (FileNotFoundException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
The onClick method runs after the user taps the profile icon. Now I will show you the database I am currently working with, this is the Firebase real-time database, not the Firebase storage. While firebase storage might be more appropriate I can't seem to figure out how to tell whos photo would be who as it does not upload them with a user id associated with them.
Database Picture Here
Instead of uploading a bitMap, a far better solution for a simple problem like yours would be Firebase Storage, similar to the Database but you can upload files such as images with much ease.
Here are the methods I currently use in my app:
private void chooseImage() {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select Picture"), PICK_IMAGE_REQUEST);
}
private void uploadImage() {
if(filePath != null)
{
final ProgressDialog progressDialog = new ProgressDialog(this);
progressDialog.setTitle("Uploading...");
progressDialog.show();
StorageReference ref = storageReference.child("images/"+userID);
ref.putFile(filePath)
.addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
progressDialog.dismiss();
toastMessage("Uploaded");
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
progressDialog.dismiss();
toastMessage("Failed"+e.getMessage());
}
})
.addOnProgressListener(new OnProgressListener<UploadTask.TaskSnapshot>() {
#Override
public void onProgress(UploadTask.TaskSnapshot taskSnapshot) {
double progress = (100.0*taskSnapshot.getBytesTransferred()/taskSnapshot
.getTotalByteCount());
progressDialog.setMessage("Uploaded "+(int)progress+"%");
}
});
}
}
I am currently trying to build a new app (complete Novice) I have run into a strange issue on the login page.The sign up process works fine connects to firebase and returns to the login screen, then allows you to login and goes to the next activity. The problem occurs when you reload the app and use the details to re-login the login button does not work until you go into the sign up activity and come out of it then the login button works fine and allows you to sign in.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
Button button = findViewById(R.id.signupbtn);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
openSignupActivity();
}
});
}
private void openSignupActivity() {
Intent intent = new Intent(LoginActivity.this, SignupActivity.class);
startActivity(intent);
setContentView(R.layout.activity_login);
LoginEmail = findViewById(R.id.LoginEmail);
LoginPassword = findViewById(R.id.LoginPassword);
Loginprogressbar = findViewById(R.id.Loginprogressbar);
mAuth = FirebaseAuth.getInstance();
findViewById(R.id.Loginbtn).setOnClickListener(this);
if conditions between
if(task.isSuccessful()){
Toast.makeText(getApplicationContext(),"Login Successful",Toast.LENGTH_SHORT).show();
finish();
startActivity(new Intent(LoginActivity.this,MainActivity.class));
#Override
public void onClick(View v) {
switch (v.getId()){
case R.id.Loginbtn:
Loginuser();
break;`enter code here`
I'm trying to make the Google Translate App using Google jar file. I have added external .jar files called google-api-translate-java-0.97 into my android project.
My code is as following
public class MainActivity extends Activity
{
String text;
//#SuppressWarnings("deprecation")
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try
{
TranslateV2.setHttpReferrer("http://code.google.com/p/google-api-translate-java/");
text = Translate.DEFAULT.execute("hello", Language.ENGLISH, Language.MARATHI);
Toast.makeText(MainActivity.this, text, Toast.LENGTH_LONG).show();
} catch (GoogleAPIException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Im getting errors as below:
Could not find method com.google.api.translate.TranslateV2.setHttpReferrer, referenced from method com.example.translator.MainActivity.onCreate
java.lang.VerifyError: com/example/translator/MainActivity
Please help me to make successful translator App using another method if your have any.
I am having two problems when trying to use "updateMessage" in a JavaFX task.
Issue #1
seems to be a known behavior, but I am not yet sure how exactly I can workaround it.This one is not (yet) critical to me.
The problem is that not all the updates I am performing in a background Task are displayed in the UI (at least the UI does not hang/freezes anymore, which was my initial issue).
My Code of the UI part:
TextArea console = new TextArea();
Button button01 = new Button("Start");
button01.setOnAction(new EventHandler() {
#Override
public void handle(Event event) {
if (ms.getState() == State.READY) {
ms.messageProperty().addListener(new ChangeListener<String>() {
#Override
public void changed(ObservableValue<? extends String> observable,
String oldValue, String newValue) {
console.appendText(newValue+"\n");
}
});
ms.start();
}
}
});
My Service:
public class MyService extends Service<Object> {
#Override
protected Task createTask() {
//here we use "MyTask" first to show problem #1
MyTask ct = new MyTask();
//here we use "MyTask2" first to show problem #2
// MyTask2 ct = new MyTask2();
try {
ct.call();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("MyService end");
return ct;
}
}
My Task (#1)
public class MyTask extends Task<Object> {
#Override
public EventHandler<WorkerStateEvent> call() {
System.out.println("call() is called");
if (Thread.currentThread().getName().equals("JavaFX Application Thread")){//yes, this might not be right, but if I do not do this, my stuff is executed twice because "call()" is called twice, but the textarea area is just updated in the second run (the non javafx application thread).
return null;
} else{
//actually here I want to do some 'heavy' stuff in the background
//and many things of this heavy stuff should be displayed / logged within the UI
//but very likely (hopefully) new messages (updateMessage) will not be send as fast as in the following loop
for (int i=0;i<10000000;i++){
updateMessage("This is update number'"+i+"' from the background thread");
}
Platform.runLater(new Runnable() {
#Override
public void run() {
try{
//here is the chance to get back to the view
}finally{
}
}
});
return null;
}
}
This basically works, but not every single loop is displayed in the UI.
How do I (correctly) make sure every loop is displayed?
Screenshot: Messages are displayed but not for every loop
Issue #2
Currently blocks my attempt to bring my little text-based game into a JavaFX application.
The main problem is that I am able to call "updateMessage" from the Task directly (see above), but not from a another (sub-)class which I would need to bring all message updates from my game (each message describes the progress of the game) to the UI.
The Task I use (Task #2):
public class MyTask2 extends Task<Object> {
#Override
public EventHandler<WorkerStateEvent> call() {
// ...
UITools myTools = new UITools();
myTools.logToUITest("Just one simple message");
// ...
Platform.runLater(new Runnable() {
#Override
public void run() {
try{
//here is the chance to get back to the view
}finally{
}
}
});
return null;
}
and the (sub-)class that I want to use to do the updateMessage (actually in my little game there would be even more classes that are called during the game and almost all of them trigger an update/message).
public class UITools {
public void logToUITest(String message){
updateMessage(message);
//how to allow 'updateMessage' from the Task to be executed from here?
}
This already results in "The method updateMessage(String) is undefined...".
How could I make it possible to call the updateMessage outside of the Task itself?
updateMessage() can only be called from within the call() method of a Task. It's a constraint imposed by the design of the Task class.
The missed message updates are due to the fact that there are too many updates and not all of them are forwarded to the event queue. Try to reduce the number of updates or sleep for a little while to separate them out in time
I have an activity which loads a data list from the server using loader callbacks. I have to list out the data into a fragment which extends
SherlockListFragment
i tried to commit the fragment using
Fragment newFragment = CategoryFragment.newInstance(mStackLevel,categoryList);
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.simple_fragment, newFragment).commit();
in onLoadFinished and it gives an IllegalStateException saying
java.lang.IllegalStateException: Can not perform this action inside of onLoadFinished
I have referred the example in actionbar sherlock, but those examples have loaders within the fragments and not the activity.
Can anybody help me with this o that I can fix it without calling the loader from the fragment!
Atlast, I have found a solution to this problem. Create a handle setting an empty message and call that handler onLoadFinished(). The code is similar to this.
#Override
public void onLoadFinished(Loader<List<Station>> arg0, List<Station> arg1) {
// do other actions
handler.sendEmptyMessage(2);
}
In the handler,
private Handler handler = new Handler() { // handler for commiting fragment after data is loaded
#Override
public void handleMessage(Message msg) {
if(msg.what == 2) {
Log.d(TAG, "onload finished : handler called. setting the fragment.");
// commit the fragment
}
}
};
The number of fragments depend on the requirement.
This method can be mainly used in case of stackFragments, where all fragments have different related functions.
As per the Android docs on the onLoadFinished() method:
Note that normally an application is not allowed to commit fragment transactions while in this call, since it can happen after an activity's state is saved. See FragmentManager.openTransaction() for further discussion on this.
https://developer.android.com/reference/android/app/LoaderManager.LoaderCallbacks.html#onLoadFinished(android.content.Loader, D)
(Note: copy/paste that link into your browser... StackOverflow is not handling it well..)
So you simply should never load a fragment in that state. If you really don't want to put the Loader in the Fragment, then you need to initialize the fragment in your onCreate() method of the Activity, and then when onLoadFinished occurs, simply call a method on your fragment.
Some rough pseudo code follows:
public class DummyFragment {
public void setData(Object someObject) {
//do stuff
}
public class DummyActivity extends LoaderCallbacks<Object> {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Fragment newFragment = DummyFragment.newInstance();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.simple_fragment, newFragment).commit();
getSupportLoaderManager.initLoader(0, null, this)
}
// put your other LoaderCallbacks here... onCreateLoader() and onLoaderReset()
public void onLoadFinished(Loader<Object> loader, Object result) {
Fragment f = getSupportLoaderManager.findFragmentById(R.id.simple_fragment);
f.setData(result);
}
Obviously, you'd want to use the right object.. and the right loader, and probably define a useful setData() method to update your fragment. But hopefully this will point you in the right direction.
As #kwazi answered this is a bad user experience to call FragmentTransition.commit() from onLoadFinished(). I have found a solution for this event by using ProgressDialog.
First created ProgressDialog.setOnDismissListener(new listener) for watching the onLoadFinished().
Further i do progressDialog.show() before getLoaderManager().restartLoader().
And eventually place progressDialog.dismiss() in onLoadFinished().
Such approach allow do not bind main UI thread and Loader's thread.
public class FrPersonsListAnswer extends Fragment
implements
LoaderCallbacks<Cursor>{
private ProgressDialog progressDialog;
#Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_persons_list, container, false);
//prepare progress Dialog
progressDialog = new ProgressDialog(curActivity);
progressDialog.setMessage("Wait...");
progressDialog.setIndeterminate(true);
progressDialog.setOnDismissListener(new OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
//make FragmentTransaction.commit() here;
//but it's recommended to pass control to your Activity
//via an Interface and manage fragments there.
}
});
lv = (ListView) view.findViewById(R.id.lv_out1);
lv.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, final View view,
final int position, long id) {
//START PROGRESS DIALOG HERE
progressDialog.show();
Cursor c = (Cursor) parent.getAdapter().getItem(position);
// create Loader
getLoaderManager().restartLoader(1, null, curFragment);
}
});
return view;
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
switch (loader.getId()) {
case 1:
//dismiss dialog and call progressDialog.onDismiss() listener
progressDialog.dismiss();
break;
default:
break;
}
}