How do I share variables between classes? - java

Say I am making something like a quiz, and I have a counter to show the number of questions that have been answered correctly. When one question is correctly answered, and a new screen(Activity) is shown, how do I carry over the number to the next screen?

When you say screens do you mean Activities? Then you probably want to pass them via extras in your intents.
Activity 1:
int score;
...
Intent Intent = new Intent(...);
intent.putExtra("score_key", score);
startActivity(intent);
Activity 2's onCreate():
int score;
...
Bundle extras = getIntent().getExtras();
// Read the extras data if it's available.
if (extras != null)
{
score = extras.getInt("score_key");
}

You can send numbers, strings, etc in a bundle with your intent.
Bundle b = new Bundle();
b.putInt("testScore", numCorrect);
Intent i = new Intent(this, MyClass.class);
i.putExtras(b);
startActivity(intent)
you can also put StringArrays and a few other simple vars

One of this way you can share your data among whole project,
public class mainClass
{
private static int sharedVariable = 0;
public static int getSharedVariable()
{
return sharedVariable;
}
}
From the other class/activity , you can access it directly using classname and . (dot) operator. e.g. mainClass.getSharedVariable();

A good practice for storing variables across Activitiys is using a own implementation of the Application Class.
public class MyApp extends android.app.Application {
private String myVariable;
public String getMyVariable() {
return myVariable;
}
public void setMyVariable(String var) {
this.myVariable = var;
}
Add the new Class in the Manifest.xml inside the application tag:
<application android:name="MyApp" android:icon="#drawable/icon" android:label="#string/app_name">
Now you can manipulate the variable in every Activity as follows:
MyApp ctx = (MyApp)getApplicationContext();
String var = ctx.getMyVariable();

Related

How can I find context and start a new Activity from Android firebase ML-Kit BarcodeScannerProcessor onSuccess

I am using the quickstart-android code provided by google but after many attempts I cam unable to find a context that is not returning null. The BarcodeScannerProcessor is not itself an Activity, so I have attempted to create an instance of the LivePreviewActivity and use that as the context in the intent, but it's null.
The goal is to once a valid barcode is recognized I want to open a new activity that allows a user to verify value and on the push of a button call a webservice to post the barcode to a database via API. I am having a hard time finding a valid context and the app is crashing when it trys to execute the Intent.
Starting at line 97-107:
https://github.com/jamiekeefer/quickstart-android/blob/master/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/barcodescanning/BarcodeScanningProcessor.java
for (int i = 0; i < barcodes.size(); ++i) {
FirebaseVisionBarcode barcode = barcodes.get(i);
BarcodeGraphic barcodeGraphic = new BarcodeGraphic(graphicOverlay, barcode);
graphicOverlay.add(barcodeGraphic);
System.out.println(barcode.getRawValue());
if (!barcode.getRawValue().equals("") ) {
System.out.println("Got the number:" + barcode.getRawValue() + " Context: " + mContext); //OLD SCHOOL DEBUG OUTPUT
//enter code to start activity
Intent intent = new Intent(mContext, SendScannedBarcode.class);
String message = scannedBarcode;
intent.putExtra(EXTRA_MESSAGE, message);
mContext.startActivity(intent);
}
}
You can back up in the repo to see the instance of the LivePreviewActivity where I trying to get context.
I have tried a number of things and read about Context, Views and Activities and basically have completely confused myself. The only tuts I can find are using Kotlin, which is not helping clarify things.
I appreacite any help in indentifying or contruting a valid Intent from this Context. Thank you.
So I am assuming that in your LivePreviewActivity you are creating an object of the class BarcodeScanningProcessor. What you can do is change the constructor in the BarcodeScanningProcessor class to accept a context and then you pass in your LivePreviewActivity's context.
This is what the code should look like:
In BarcodeScanningProcessor:
public BarcodeScanningProcessor(Context context) {
// Note that if you know which format of barcode your app is dealing with, detection will be
// faster to specify the supported barcode formats one by one, e.g.
// new FirebaseVisionBarcodeDetectorOptions.Builder()
// .setBarcodeFormats(FirebaseVisionBarcode.FORMAT_QR_CODE)
// .build();
detector = FirebaseVision.getInstance().getVisionBarcodeDetector();
this.mContext = context;
}
Then in LivePreviewActivity:
In the particular case of your activity you would do:
case BARCODE_DETECTION:
Log.i(TAG, "Using Barcode Detector Processor");
cameraSource.setMachineLearningFrameProcessor(new BarcodeScanningProcessor(getApplicationContext()));
break;
Or if you just wanted to create an object of the class you could do:
BarcodeScanningProcessor bsp = new BarcodeScanningProcessor(getApplicationContext());
This should now give your BarcodeScanningProcessor class the context of your activity. Now, in BarcodeScanningProcessor, mContext should not be null and will have the context of your activity. I hope this answers your question.
try this create Application class
import android.app.Application;
public class MyApplication extends Application {
static MyApplication instance;
#Override
public void onCreate() {
super.onCreate();
instance=this;
}
public static MyApplication getInstance() {
return instance;
}
}
Register in manifest file
<application
..
android:name="com.yourpackage.MyApplication"
..>
.
.
.
</application>
start activity using this MyApplication.
Intent intent = new Intent(MyApplication.getInstance(), SendScannedBarcode.class);
String message = scannedBarcode;
intent.putExtra(EXTRA_MESSAGE, message);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MyApplication. getInstance().startActivity(intent);
Another way of handling the issue is create new constructor of BarcodeScanningProcessor which takes interface call back and once processing is done pass back result to caller.
public interface BarcodeUpdateListener {
#UiThread
void onBarcodeDetected(Barcode barcode);
}
private BarcodeUpdateListener callback;
public BarcodeScanningProcessor(BarcodeUpdateListener callback){
this.callback = callback;
detector = FirebaseVision.getInstance().getVisionBarcodeDetector();
}
Once you get the result pass result to caller
callback.onBarcodeDetected(<Barcode>)
You can get the context from graphicOverlay:
Context context = graphicOverlay.getContext();

How can I go to second activity but send a data to another activity?

I made an application "Quiz", which has 4 activities. Main activity sends a String with your name from EditText to activity with first question. I have a problem here, because I don't know how to send this string immediately to final activity from main activity, but without going to final activity. I want to go to Activity with first question from main activity, then to activity with second question, and in the end I want to go to final activity.
Thanks for your help!
You could use static fields to pass data.
Inside your FinalActivity class you could add the following variable:
private static String NAME = "";
And with the following getters and setters:
public static String getName(){
return NAME;
}
public static void setName(String name){
NAME = name;
}
You can use the getter setter here at Application class so you can get the string data from anywhere were you want to. This is not the only way but i think it is also the easy way.
public class MyApplication extends Application {
private String someVariable;
public String getSomeVariable() {
return someVariable;
}
public void setSomeVariable(String someVariable) {
this.someVariable = someVariable;
}
}
add this in your manifest
<application
android:name=".MyApplication"
android:icon="#drawable/icon"
android:label="#string/app_name">
hen in your activities you can get and set the variable like so:
/ set
((MyApplication) this.getApplication()).setSomeVariable("foo");
// get
String s = ((MyApplication) this.getApplication()).getSomeVariable();
Some Url which may help you Android global variable
You can use shared preference also but as per our requirement i don't recommend that to you
Android Shared preferences example
You can use Broadcast Receiver for your requirement. In your activity from which you want to send data, do this way:
Intent intent = new Intent();
intent.setAction("fourthactivity");
sendBroadcast(intent);
And In your fourth activity, make a broadcast receiver which receive your intent :
public class IncomingReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("fourthactivity")) {
System.out.println("GOT THE INTENT");
}
}
}
Tell me if this doesn't work or click right if it works for you.
You can use SharedPreference to store the answers as you go from one activity to other and later compare all the answers in the FinalActivity in that way less complex coding and you will achieve your desired result.

Passing Data Between Activities in Android App

Hey I am pretty new to making android apps and I understand that the easiest way to pass data between two activities is through an intent.
In one of my classes (EventOptions.java), I call this line of code:
Intent i = new Intent(EventOptions.this, PhotoFetcher.class);
i.putExtra("imageArray", imageIDs);
startActivity(i);
imageIDs is a string array
In my PhotoFetcher class, I want to set a string array called imageIDs to the imageIDs string array that I am passing through the intent.
I want to set images as a global variable in my class:
public class MainActivity extends Activity implements View.OnClickListener{
Intent it = getIntent();
String[] imageIDs = it.getStringArrayExtra("imageArray");
...
}
This crashes my app however. Is this not allowed? And if so, how can I fix it? Thanks in advance!
Need to call getIntent() in a method instead of at class level. call it inside onCreate :
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
// get Intent here
Intent it = getIntent();
String[] imageIDs = it.getStringArrayExtra("imageArray");
}
if I want to use the imageIDs array in another public class defined
in my PhotoFetcher class, do I need to call it again?
To get imageIDsin PhotoFetcher class either declare String[] imageIDs as global variable or pass imageIDs using PhotoFetcher class constructor
You have to use putStringArrayListExtra. You can convert your String[] to an ArrayList first.
Like so
ArrayList<String> arrayList = new ArrayList<String>(Arrays.asList(imageIDs));
Intent i = new Intent(EventOptions.this, PhotoFetcher.class);
i.putStringArrayListExtra("imageArray", arrayList);
startActivity(i);
And then you can fetch it like you do, preferably in onCreate or after that call.
Intent it = getIntent();
ArrayList<String> imageIDs = it.getStringArrayListExtra("imageArray");
Share data without persisting to disk
It is possible to share data between activities by saving it in memory given that, in most cases, both activities run in the same process.
Note: sometimes, when the user leaves your activity (without quitting it), Android may decide to kill your application. In such scenario, I have experienced cases in which android attempts to launch the last activity using the intent provided before the app was killed. In this cases, data stored in a singleton (either yours or Application) will be gone and bad things could happen. To avoid such cases, you either persist objects to disk or check data before using it to make sure its valid.
Use a singleton class
Have a class to whole the data:
public class DataHolder {
private String data;
public String getData() {return data;}
public void setData(String data) {this.data = data;}
private static final DataHolder holder = new DataHolder();
public static DataHolder getInstance() {return holder;}
}
From the launched activity:
String data = DataHolder.getInstance().getData();
Use application singleton (I would recommend this)
The application singleton is an instance of android.app.Application which is created when the app is launched. You can provide a custom one by extending Application:
import android.app.Application;
public class MyApplication extends Application {
private String data;
public String getData() {return data;}
public void setData(String data) {this.data = data;}
}
Before launching the activity:
MyApplication app = (MyApplication) getApplicationContext();
app.setData(someData);
Then, from the launched activity:
MyApplication app = (MyApplication) getApplicationContext();
String data = app.getData();
ρяσѕρєя K hit the nail on the head, you're running a method where constructors and fields go. To make the variables (the imageIDs) global, it's quite simple and there are a few ways of doing it. Declare them outside any method, and then assign them in your onCreate or onResume (which will always be called).
Try this:
public class MainActivity extends Activity implements View.OnClickListener {
//global variable
String[] imageIDs;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// get Intent here
Intent it = getIntent();
imageIDs = it.getStringArrayExtra("imageArray");
}
}

How to pass an object without intent

Currently I am able to pass an object called Exhibit to another Activity by putting it into putExtras and starting the intent. Now, what if I want to pass the object to another object?
For example I send like this:
public void onListItemClick(ListView parent, View v, int position, long id) {
Intent i = new Intent(this, ExhibitOpen.class);
Bundle bundle = new Bundle();
bundle.putSerializable("MyClass", (Serializable) exhibits.get(position));
i.putExtras(bundle);
startActivity(i);
}
Then I receive:
Intent i = getIntent();
dene = (Exhibit)i.getSerializableExtra("MyClass");
Here you can see that I am passing exhibits.get(position) to certain class and start the class as new activity, then the new activity receives it. So, how can I pass the object to another class (not this class) without starting it?
Thanks a lot!
If you don't want your object to be persisted during app launches, you can just set it as a static instance variable of your application class:
public class MyApp extends Application {
private static Exhibit sExhibit;
public static void setExhibit(Exhibit exhibit) {
sExhibit = exhibit;
}
public static Exhibit getExhibit() {
return sHexhibit;
}
}
// To set the object:
MyApp.setExhibit(myExhibit);
// To retrieve it
Exhibit myExhibit = MyApp.getExhibit()
If you don't want to extend your application, you can just do it in any class, or in your Exhibit model, wherever it would make the more sense.
If you want it to persist in between app launches and it's serializable, I would use the Shared Preferences to store it: http://developer.android.com/guide/topics/data/data-storage.html#pref
You can just call a method on the object:
otherObject.someMethod(dene);
Please check this LINK1 , LINK2 and LINK3

Passing custom objects between activities?

How do I pass custom objects between activites in android? I'm aware of bundles but I can't seem to see any functionality for this in them. Could anyone show me a nice example of this?
You should implement Parcelable interface.
Link to documentation.
Using Parcelable interface you can pass custom java object into the intent.
1) implement the Parcelable interface to your class like:
class Employee implements Parcelable
{
}
2) Pass the Parcelable object into the intent like:
Employee mEmployee =new Employee();
Intent mIntent = new Intent(mContect,Abc.class);
mIntent.putExtra("employee", mEmployee);
startActivity(mIntent);
3) Get the data into the new [Abc] Activity like:
Intent mIntent = getIntent();
Employee mEmployee = (Employee )mIntent.getParcelableExtra("employee");
a Parcel MIGHT solve your problem.
think of a Parcel as an "array" (metaphorical) of primitive types (long, String, Double, int, etc). if your custom class is composed of primitive types ONLY, then change your class declaration including implements Parcelable.
you can pass a parcelable object thru an intent with no difficulty whatsoever (just like you would send a primitive-typed object). in this case i have a parcelable custom class called FarmData (composed of longs, strings and doubles) which i pass from one activity to another via intent.
FarmData farmData = new FarmData();
// code that populates farmData - etc etc etc
Intent intent00 = new Intent(getApplicationContext(), com.example.yourpackage.yourclass.class);
intent00.putExtra("farmData",farmData);
startActivity(intent00);
but retrieving it may be tricky. the activity that receives the intent will check if a bundle of extras was send along with the intent.
Bundle extras = getIntent().getExtras();
FarmData farmData = new FarmData();
Intent intentIncoming = getIntent();
if(extras != null) {
farmData = (FarmData) intentIncoming.getParcelableExtra("farmData");// OK
}
Given an object PasswordState that implements Serializable throughout the object tree, you can pass this object to anther activity as in:
private void launchManagePassword() {
Intent i= new Intent(this, ManagePassword.class); // no param constructor
PasswordState outState= new PasswordState(lengthKey,timeExpire,isValidKey,timeoutType,"",model.getIsHashPassword());
Bundle b= new Bundle();
b.putSerializable("jalcomputing.confusetext.PasswordState", outState);
i.putExtras(b);
startActivityForResult(i,REQUEST_MANAGE_PASSWORD); // used for callback
}
One simple way to pass an object between activities or make a object common for all applicattion, is create a class extending Application.
Here is a example:
public class DadosComuns extends Application{
private String nomeUsuario="";
public String getNomeUsuario() {
return nomeUsuario;
}
public void setNomeUsuario(String str) {
nomeUsuario = str;
}
}
In all your others activities, you just need instantiate one object "DadosComuns", declarating as a Global Variable.
private DadosComuns dadosComuns;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//dados comuns
dadosComuns = ((DadosComuns)getApplicationContext());
dadosComuns.setNomeUsuario("userNameTest"); }
All others activities that you instantiate dadosComuns = ((DadosComuns)getApplicationContext()); you can acess getNomeUsuario() == "userNameTest"
In your AndroidManifest.xml you need to have
<application
android:name=".DadosComuns"

Categories