I'm trying to send an object created from the Spotify API (a SpotifyAppRemote instance) from my MainActivity class to a BackgroundService (implemented as IntentService).
Since I can't use parcelable to send my object as I have no control over the API I was trying to use GSON to send it via the putExtra method from my intent like this:
intent.putExtra("spotifyRemote", gson.toJson(mSpotifyAppRemote, SpotifyAppRemote.class));
However, on runtime I get an error:
java.lang.UnsupportedOperationException: Attempted to serialize java.lang.Class: com.spotify.protocol.types.ImageUri. Forgot to register a type adapter?
Is there another way to send this object to my Service? Looking for this error message didn't really help.
Here's the code from my MainActivity class:
#Override
public void onConnected(SpotifyAppRemote spotifyAppRemote) {
mSpotifyAppRemote = spotifyAppRemote;
getCurrentTrack();
// Now you can start interacting with App Remote
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View v) {
infoText.setText("Successfully started!");
counter = 1;
numSongs = Integer.parseInt(mEdit.getText().toString());
PlayerApi playerApi = mSpotifyAppRemote.getPlayerApi();
playerApi.seekTo(0);
playerApi.resume();
Intent intent = new Intent(MainActivity.this, BackgroundService.class);
intent.putExtra("counter", counter);
intent.putExtra("numSongs", numSongs);
intent.putExtra("firstTrack", gson.toJson(curTrack, Track.class));
intent.putExtra("spotifyRemote", gson.toJson(mSpotifyAppRemote, SpotifyAppRemote.class));
startService(intent);
}
});
}
I worked around this by declaring a static variable in my Service and setting the variable in my MainActivity like this:
BackgroundService.mSpotifyAppRemote = mSpotifyAppRemote;
Declaration in my Service:
public static SpotifyAppRemote mSpotifyAppRemote = null;
Related
I would like know how to send a command to an activity which has started from inside another function. More precisely I want to send a pause intent to com.google.vr:sdk... the view is started like this:
class VRPlayer {
private void playVideo(int sourceType, Context context) {
Intent intent = new Intent(context, VrVideoActivity.class);
intent.setAction(Intent.ACTION_VIEW);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
private void pauseVideo(Context context, JSONArray args) {
VrVideoActivity.class.toggleVideoPlay(); <------------- NOT WORKING ¯\_(-_- )_/‾
}
}
once the activity has started there should be a way to execute other function, ex: toggleVideoPlay() which are inside the VrVideoAcitivity from the but I can't get the right way to do it... If you want to try it you can find the Android project here: https://github.com/StarStep/android-help-vr
VrVideoActivity vrVideoActivity = new VrVideoActivity();
vrVideoActivity.toggleVideoPlay();
a simple way -> (new VrVideoActivity).toggleVideoPlay();
another way -> set the toggleVideoPlay(); to static as following
public static void toggleVideoPlay()
{
//Your Code
}
and call it VrVideoActivity.toggleVideoPlay();
I´m pretty new in android. I have made communication between two Apps with BroadcastReceiver and intentServices .
The thing is, I want to send information to the app2 from app1. In app1 I need to access a variable which is in MainActivity.class , I need to send it to servicev.class (the service where the intent is handled) but the variable "res" is null when I access it, why does that happen? (App2 calls app1 onHandleIntent and it breaks in res.getOtp() ) I try to create an extra setter getter class and also an intent but getIntent() does not work inside onHandleIntent... how can I achieve to pass res.getOTP (string) ? I really dont want to use SQLite
servicev:
public class servicev extends IntentService {
private static final int RESULT_OK = 1;
protected ResultReceiver mReceiver;
public servicev() {
super("yeah");
}
#Override
protected void onHandleIntent(Intent intent) {
//I receive here the intent from app2 and I need to response with res.getOTP()
helper h = new helper();
String val = intent.getStringExtra("foo");
Intent in = new Intent("com.banorte.bem.movil.veriToken.SendBroadcast");
in.putExtra("resultCode", this.RESULT_OK);
in.putExtra("resultValue", "My Result Value. Passed in: " + h.getRes().getOtp()); //h here is null... setter and getter approach does not work... maybe sqlite could work but it is necesary?
sendBroadcast(in);
}
}
MainActivity:
public class MainActivity extends AppCompatActivity {
VTTokenAPI api;
TextView textView;
Button button;
EditText input;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AndroidSetup.getInstance().init(this);
helper h = new helper();
api = new VTTokenAPI("FFFFFF");
res = api.getStatus();
res.getOtp(); //correct value
h.setRes(res);
setContentView(R.layout.activity_main);
}
}
helper:
public class helper {
public VTResult getRes() {
return res;
}
public void setRes(VTResult res) {
this.res = res;
}
VTResult res;
}
You are trying to instantiate a new MainActivity which is not the same as the running activity but a new instance.
If you need your IntentService to be able to get data from a running Activity you have options such as using SharedPreferences or SQLite. Instead of keeping the data in memory try to persist it in some database in the onCreate and then try to read it from the storage during handleIntent
When I run the app there is an Fatal exception error
android.content.ActivityNotFoundException: No Activity found to handle Intent
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// get butten
Button bt= (Button) findViewById(R.id.bt);
// set a monitor
bt.setOnClickListener(new MyListener());
}
class MyListener implements View.OnClickListener{
public void onClick(View v) {
EditText et = (EditText) findViewById(R.id.et);
String number = et.getText().toString();
Intent intent = new Intent();
intent.setAction(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel"+number));
startActivity(intent);
}
}
}
Very simple, your device does not have an app that handles phone calls. It is probably a tablet. When coding, you have to code for such errors, by using try...catch.
You have to specify the Intent by using a context & class name.
Since you haven't provide your Manifest file the easiest way to avoid the error is changing the code as follows
Intent intent = new Intent(this,MainActivity.class);
More details from android Documentation
android.content.Intent public Intent(android.content.Context packageContext,
java.lang.Class<?> cls)
Create an intent for a specific component. All other fields (action, data, type, class) are
null, though they can be modified later with explicit calls. This
provides a convenient way to create an intent that is intended to
execute a hard-coded class name, rather than relying on the system to
find an appropriate class for you; see setComponent for more
information on the repercussions of this.
Parameters: packageContext - A Context of the application package
implementing this class. cls - The component class that is to be
used for the intent.
I have creted a program that has 3 Activities: MainActivity, UpgradeActivity and UpgradesActivity.
Main Activity contains a timer and it also contains an instance of a Vehicle class.
public class MainActivity extends Activity {
TextView vehicleSpeed, vehicleName, vehicleDistance, vehicleLocation,
vehicleStatus, vehicleNews, vehicleInfo, vehicleMoney;
ProgressBar vehicleFuel;
public static Vehicle vehicle;
boolean launched;
public static PartType selectedType;
Handler handler = new Handler();
I have a button in MainActivity, that when pressed will take me to a page where i can select which part of the vehicle i wish to upgrade. For example i select: Engine. The engine Button takes me to the Upgrade Activity. In this activity i can buy the upgrade which should be applied to the vehicle in MainActivity. For the purpose of this question, lets say it set vehicles speed to +3.
My question is in regards to how to access the vehicle instance inside the MainActivity from the UpgradeActivity. I've tried making the instance static but that didn't work. How do i gain access and how can i change the vehicles variables from the other activities.
Here is where i am making the instance:
#Override
protected void onCreate(Bundle savedInstanceState) {
this.selectedType = PartType.Antenna;
this.launched = false;
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
vehicle = new Vehicle();
vehicle.setupCar();
Here is where i am accessing the variable in Upgrades, it call the upgrade function inside of the Vehicle Class:
buyUp1.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
MainActivity.vehicle.upgradeEngine(MainActivity.vehicle.engineLvl + 1);
Intent activityChangeIntent = new Intent(UpgradesActivity.this, MainActivity.class);
UpgradesActivity.this.startActivity(activityChangeIntent);
}
});
And this is the function within the Vehicle Class:
public void upgradeEngine(int lvl) {
engineLvl += 3;
engine = parts.getEngine(lvl);
}
The vehicle Stores an integer called: EngineLvl. This determines what level the cars engine is. The level is incremented by +3 everytime the engine is updated.
The problem is that the engine level never changes. Even if i make the Vehicle instance and all of the variables within vehicle STATIC;
MAINACTIVITY:
Vehicle
Button to UpgradesActivity
UPGRADESACTIVITY:
Button to UpgradeActivity
UPGRADEACTIVITY:
Change vehicle enginelvl Int
Button back to MainActivity
Main>Upgrades>Upgrade
Thank you for your time
Hard to say what is wrong without seeing the code, but I would advise you to use the Intent extras to move your data between activities. You will need to make your Vehicle class implement Parcelable (there is an example of how to implement Parcelable on that page, and countless others on the net). You pass your object as extra to the intent launching your UpgradeActivity like this :
Intent upgradeIntent = new Intent(this, UpgradeActivity.class);
upgradeIntent.putExtra("com.example.model.Vehicle", yourVehicleObject);
startActivityForResult(upgradeIntent, UPGRADE_CAR_REQUEST_CODE);
//UPGRADE_CAR_REQUEST_CODE is a unique private static final int
Then you can retrieve it in your UpgradeActivity onCreate method :
Intent intent = getIntent();
Vehicle vehicleFromLastActivity = intent.getParcelableExtra("com.example.model.Vehicle");
Before going back to your MainActivity you do something like this :
Intent dataIntent = new Intent();
dataIntent.putExtra("com.example.model.Vehicle", yourModifiedVehicleObject);
setResult(RESULT_OK, dataIntent);
finish();
Then finally in MainActivity you need to handle the result, it is done like this :
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch(requestCode) {
case UPGRADE_CAR_REQUEST_CODE:
if(resultCode == android.app.Activity.RESULT_OK) {
Vehicle modifiedObject = data.getParcelableExtra("com.example.model.Vehicle");
// Now you can use that object which is coming from UpgradeActivity
}
}
}
Of course this could cause issues if your Vehicle class takes a lot of memory. You could then consider passing only the relevant information through the Intent to rebuild the object in the UpgradeVehicle Activity, for example only the id & name.
I`m trying to parse an object from my my main activity to a new activity that starts when the user clicks a button. I've seached the internet and found how to parse primative types and custom made classes that implements parceble or serilizable, but can't find any information on how to transfeer a raw object.
I'll write psuedo-code of what I`m trying to achive below:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
loadConnectInfo();
View connectButton = findViewById(R.id.connectButton);
connectButton.setOnClickListener(this);
}
public void onClick(View v) {
switch (v.getId()) {
case R.id.connectButton:
Intent i = new Intent(this, NewClass.class);
Socket s = connect(); // this is the object I want to parse to to "NewClass"
startActivity( i);
break;
}
You can't pass an object that is neither serializable nor parcelable between activities this way. What you probably want to do in this case is make your code that manages and interacts with the socket into a service and bind to that service in all the activities that need to use it.
Sometimes when I had to pass variable from one class to another I've used static variables in class which I deliver some objects. This will work but it is not recommended way to pass object in Android and you don't have guaranty that will work always.. Here you should check if your delivered object is not null of course.
public void onClick(View v) {
switch (v.getId()) {
case R.id.connectButton:
Intent i = new Intent(this, NewClass.class);
Socket s = connect(); // this is the object I want to parse to to "NewClass"
//Here using static field of class you pass variable to NewClass
//You can access this value in NewClass like that: NewClass.StaticSocket
//Warning: This is not a standar android scheme but I tested and it works
//with Date object
NewClass.StaticSocket = s;
startActivity( i);
break;
}
On second activity:
public void onCreate(Bundle savedInstanceState) {
Log.i("StaticVar","NewClass.StaticSocket: "+ NewClass.StaticSocket.toString());
There are already other posts about this:
What's the best way to share data between activities?
BTW, be careful: objects like sockets are not meant to be shared by bundles through the intent because they shouldn't be serialized. Maybe using a global state, like a singleton does it for you.