service data reset after swiping away application - java

Purpose of program: I'm trying to make an app that will count how many times the user checked their phone by issuing a broadcast for Intent.ACTION_SCREEN_ON. it then increments a counter and updates the activity with the new counter.
The problem: This all works just fine but as soon as I swipe away the application from the apps tray, the counter goes back to zero.
obviously what is supposed to happen is the counter would continue.
I tried saving the counter value in the service onDestroy and then calling it again onCreate but onDestroy is never called.
Note that in the onCreate() for the activity it sends a broadcast to the service asking for the most recent value of counter and then updates it in the view. I couldn't find a better way to keep them in sync.
CounterService.java
public class CounterService extends Service {
public static boolean RERUN = true;
private int counter = 0;
private SharedPreferences SP;
private BroadcastReceiver mScreenStateBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
counter++;
System.out.println("************************************* \n \n " + counter);
}
sendCounterBroadcast();
}
};
public void sendCounterBroadcast() {
Intent i = new Intent();
i.setAction("com.inc.count");
i.putExtra("counterValue", counter);
sendBroadcast(i);
}
#Override
public void onCreate() {
super.onCreate();
System.out.println("********************** CounterService.onCreate()");
// get counter value from SP -- this is useful for when the service gets recreated
SP = getSharedPreferences("Counter Service Data", MODE_PRIVATE);
counter = SP.getInt("counter", 0);
// wait for screen to be turned on or for the activity to ask you for the counter number
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_SCREEN_ON);
intentFilter.addAction("send.counter.to.phonecounteractivity");
registerReceiver(mScreenStateBroadcastReceiver, intentFilter);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return Service.START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
System.out.println("***************************************** CounterService.OnDestroy()");
unregisterReceiver(mScreenStateBroadcastReceiver);
// Save counter value for when we restart service
SP = getSharedPreferences("Counter Service Data", MODE_PRIVATE);
SharedPreferences.Editor SPE = SP.edit();
if (RERUN) {
SPE.putInt("counter", counter);
System.out.println("******************************** RESTARTING SERVICE ");
startService(new Intent(getApplicationContext(), CounterService.class));
} else
SPE.putInt("counter", 0);
SPE.apply();
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
PhoneCheckerCounter.Java
public class PhoneCheckerCounter extends AppCompatActivity {
private BroadcastReceiver changeCount;
private IntentFilter filter;
private int counter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_phone_checker_counter);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
switcherOnClick();
assignValuesOnCreate();
System.out.println("**************************** onCreate()");
changeCounterText();
}
public void switcherOnClick() {
final Switch sCounter = findViewById(R.id.switchCounter);
sCounter.setOnClickListener(new View.OnClickListener() {
Intent intent = new Intent(getApplicationContext(), CounterService.class);
#Override
public void onClick(View v) {
if (sCounter.isChecked()) {
startService(intent);
CounterService.RERUN = true;
v.getContext().registerReceiver(changeCount, filter);
Toast.makeText(getApplicationContext(), "Counting has begun", Toast.LENGTH_SHORT).show();
} else {
TextView n = findViewById(R.id.counter);
n.setText("0");
CounterService.RERUN = false;
v.getContext().unregisterReceiver(changeCount);
stopService(intent);
Toast.makeText(getApplicationContext(), "The application stopped counting", Toast.LENGTH_SHORT).show();
}
}
});
}
public void changeCounterText() {
changeCount = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
TextView n = findViewById(R.id.counter);
counter = intent.getIntExtra("counterValue", 0);
System.out.println("************************ RECEIVED!!!! value of: " + counter);
n.setText("" + counter);
}
};
filter = new IntentFilter();
filter.addAction("com.inc.count");
this.registerReceiver(changeCount, filter);
}
#Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(changeCount);
assignValuesOnDestroy();
System.out.println("**************************** onDestroy()");
}
public void assignValuesOnCreate() {
Switch s = findViewById(R.id.switchCounter);
if (getSwitchValueFromSP() == 1) s.setChecked(true);
else s.setChecked(false);
Intent f = new Intent();
f.setAction("send.counter.to.phonecounteractivity");
sendBroadcast(f);
}
public void assignValuesOnDestroy() {
SharedPreferences SP = getSharedPreferences("data", MODE_PRIVATE);
SharedPreferences.Editor edit = SP.edit();
Switch s = findViewById(R.id.switchCounter);
if (s.isChecked()) edit.putInt("switch", 1);
else edit.putInt("switch", 0);
edit.apply();
}
public int getSwitchValueFromSP() {
SharedPreferences SP = getSharedPreferences("data", MODE_PRIVATE);
int isOn = SP.getInt("switch", 0);
return isOn;
}
}
Sample of the activity

Related

Close the activity from a broadcast receiver

My Project is about the call recorder.
I want when the call received, my transparent activity open with a button.
I open my activity from my broadcast receiver class.
in this activity, I have a toggle button to activate or deactivate my application.
When a call received, if my toggle button is on, it starts to record the call.
it works OK but when the call is finished, I close my activity from my broadcast receiver class.
like this: first, this is my activity when the call received:
public class Test extends Activity {
static Test tes;
ToggleButton toggleButton;
TextView txt_disable, txt_enable;
private static Context context;
private BroadcastReceiver _closeActivityReceiver = new CloseActivityReceiver();
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.test);
tes = this;
IntentFilter filter = new IntentFilter("closeNoInternetActivity");
this.registerReceiver(_closeActivityReceiver, filter);
toggleButton = findViewById(R.id.togglebtn);
txt_enable = findViewById(R.id.txt_enable);
txt_disable = findViewById(R.id.txt_disable);
if (isActivityRunning(MainActivity.class)) {
MainActivity.getInstance().finish();
}
final SharedPreferences pref = getSharedPreferences("TOGGLE", MODE_PRIVATE);
boolean sie = pref.getBoolean("STATE", true);
if (sie == true) {
Log.i("mhs", "true");
//to main activity toggleRecord fal hast pass inja user agar bekhad mitone k disable kone
toggleButton.setChecked(true);
toggleButton.setText(null);
toggleButton.setTextOn(null);
toggleButton.setTextOff(null);
toggleButton.setBackgroundResource(R.drawable.record_btn);
txt_disable.setVisibility(View.VISIBLE);
toggleButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
toggleRecord.setChecked(false);
toggleButton.setBackgroundResource(R.drawable.not_recording_btn);
finishAffinity();
}
});
} else {
Log.i("mhs", "false");
toggleButton.setChecked(false);
toggleButton.setText(null);
toggleButton.setTextOn(null);
toggleButton.setTextOff(null);
toggleButton.setBackgroundResource(R.drawable.not_recording_btn);
txt_enable.setVisibility(View.VISIBLE);
toggleButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
toggleRecord.setChecked(true);
toggleButton.setBackgroundResource(R.drawable.record_btn);
finishAffinity();
}
});
}
}
protected Boolean isActivityRunning(Class activityClass) {
ActivityManager activityManager = (ActivityManager) getBaseContext().getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> tasks = activityManager.getRunningTasks(Integer.MAX_VALUE);
for (ActivityManager.RunningTaskInfo task : tasks) {
if (activityClass.getCanonicalName().equalsIgnoreCase(task.baseActivity.getClassName()))
return true;
}
return false;
}
private class CloseActivityReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// close this damn activity!
}
}
#Override
public void onDestroy() {
super.onDestroy();
this.unregisterReceiver(this._closeActivityReceiver);
}
public static Test getInstance() {
return tes;
}
}
and here is my receiver:
here I start an activity from the receiver like this when I have a phone call
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
isIncoming = true;
callStartTime = new Date();
savedNumber = number;
onIncomingCallStarted(context, number, callStartTime);
Intent i = new Intent(context, Test.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
Log.i("mhs","zang khord");
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
if (lastState != TelephonyManager.CALL_STATE_RINGING) {
isIncoming = false;
callStartTime = new Date();
onOutgoingCallStarted(context, savedNumber, callStartTime);
Log.i("mhs","ghat kard");
} else {
isIncoming = true;
callStartTime = new Date();
onIncomingCallAnswered(context, savedNumber, callStartTime);
//vaghti zang mikhore va ghat mikone dar akhar
Log.i("mhs","ghatid");
Intent in = new Intent("closeNoInternetActivity");
context.sendBroadcast(in);
}
and here I close it like this:
case TelephonyManager.CALL_STATE_OFFHOOK:
if (lastState != TelephonyManager.CALL_STATE_RINGING) {
isIncoming = false;
callStartTime = new Date();
onOutgoingCallStarted(context, savedNumber, callStartTime);
Log.i("mhs","ghat kard");
} else {
isIncoming = true;
callStartTime = new Date();
onIncomingCallAnswered(context, savedNumber, callStartTime);
//vaghti zang mikhore va ghat mikone dar akhar
Log.i("mhs","ghatid");
Intent in = new Intent("closeNoInternetActivity");
context.sendBroadcast(in);
}
My problem is that I think my activity doesn't close, and it reminds in the background and causes my activity is transparent, then again I have a phone call. my ringing screen doesn't show on screen.
I think If I able to close my Test activity in right way, my problem solved.
Just copy and paste below code. it should work. If it doesn't then try modifying finish method you can explicitly call destroy method if needed.
public class Test extends Activity {
static Test tes;
private static Context context;
ToggleButton toggleButton;
TextView txt_disable, txt_enable;
private BroadcastReceiver _closeActivityReceiver = new CloseActivityReceiver();
public static Test getInstance() {
return tes;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.test);
tes = this;
IntentFilter filter = new IntentFilter("closeNoInternetActivity");
this.registerReceiver(_closeActivityReceiver, filter);
toggleButton = findViewById(R.id.togglebtn);
txt_enable = findViewById(R.id.txt_enable);
txt_disable = findViewById(R.id.txt_disable);
if (isActivityRunning(MainActivity.class)) {
MainActivity.getInstance().finish();
}
final SharedPreferences pref = getSharedPreferences("TOGGLE", MODE_PRIVATE);
boolean sie = pref.getBoolean("STATE", true);
if (sie == true) {
Log.i("mhs", "true");
//to main activity toggleRecord fal hast pass inja user agar bekhad mitone k disable kone
toggleButton.setChecked(true);
toggleButton.setText(null);
toggleButton.setTextOn(null);
toggleButton.setTextOff(null);
toggleButton.setBackgroundResource(R.drawable.record_btn);
txt_disable.setVisibility(View.VISIBLE);
toggleButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
toggleRecord.setChecked(false);
toggleButton.setBackgroundResource(R.drawable.not_recording_btn);
finishAffinity();
}
});
} else {
Log.i("mhs", "false");
toggleButton.setChecked(false);
toggleButton.setText(null);
toggleButton.setTextOn(null);
toggleButton.setTextOff(null);
toggleButton.setBackgroundResource(R.drawable.not_recording_btn);
txt_enable.setVisibility(View.VISIBLE);
toggleButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
toggleRecord.setChecked(true);
toggleButton.setBackgroundResource(R.drawable.record_btn);
finishAffinity();
}
});
}
}
protected Boolean isActivityRunning(Class activityClass) {
ActivityManager activityManager = (ActivityManager) getBaseContext().getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> tasks = activityManager.getRunningTasks(Integer.MAX_VALUE);
for (ActivityManager.RunningTaskInfo task : tasks) {
if (activityClass.getCanonicalName().equalsIgnoreCase(task.baseActivity.getClassName()))
return true;
}
return false;
}
#Override
public void onDestroy() {
super.onDestroy();
this.unregisterReceiver(this._closeActivityReceiver);
}
public void finish() {
super.finish();
}
private class CloseActivityReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// close this damn activity!
finish();
}
}
}

how to send data from background service to activity?

i try almost code in the internet, but i can't solve it.
i want to send data from specific method in the service to activity.
i use intent(putExtra), but it doesn't go to activity class.
here is my RecoBackgroundRangingService.java
(i omit unnecessary code)
private static final String TAG = "RecoBackgroundRangingService";
public static final String BROADCAST_ACTION = "com.example.hello ";
private final Handler handler = new Handler();
Intent intent;
int counter = 0;
#Override
public void onCreate() {
Log.i("BackRangingService", "onCreate()");
super.onCreate();
intent = new Intent(BROADCAST_ACTION);
Toast.makeText(getBaseContext(),"on create", Toast.LENGTH_SHORT).show();
}
#Override
public void didEnterRegion(RECOBeaconRegion region, Collection<RECOBeacon> beacons) {
/**
* For the first run, this callback method will not be called.
* Please check the state of the region using didDetermineStateForRegion() callback method.
*
//Get the region and found beacon list in the entered region
Log.i("BackRangingService", "didEnterRegion() - " + region.getUniqueIdentifier());
this.popupNotification("Inside of " + region.getUniqueIdentifier());
//Write the code when the device is enter the region
DisplayLoggingInfo();
Toast.makeText(getBaseContext(),"did enter region", Toast.LENGTH_SHORT).show();
//this.startRangingWithRegion(region); //start ranging to get beacons inside of the region
//from now, stop ranging after 10 seconds if the device is not exited
}
private void DisplayLoggingInfo() {
//Log.d(TAG, "entered DisplayLoggingInfo");
//intent.putExtra("time", new Date().toLocaleString());
//intent.putExtra("counter", String.valueOf(++counter));
intent.putExtra("status", 1);
sendBroadcast(intent);
Toast.makeText(getBaseContext(),"display logging", Toast.LENGTH_SHORT).show();
}
here is my CheckActivity.java
(when i receive data, my purpose is that store data to the server. therefore, i don't need to use layout. So, in order to check data, i use toast "hello". but toast never popup my phone...)
public class CheckActivity extends Activity {
private static final String TAG = "CheckActivity";
private Intent intent;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_check);
intent = new Intent(this, RecoBackgroundRangingService.class);
Toast.makeText(getBaseContext(), "check activity", Toast.LENGTH_SHORT).show();
}
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
updateUI(intent);
}
};
#Override
public void onResume() {
super.onResume();
startService(intent);
registerReceiver(broadcastReceiver, new IntentFilter(RecoBackgroundRangingService.BROADCAST_ACTION));
}
#Override
public void onPause() {
super.onPause();
unregisterReceiver(broadcastReceiver);
stopService(intent);
}
private void updateUI(Intent intent) {
int status = intent.getIntExtra("status", -1);
Toast.makeText(getBaseContext(), "hello", Toast.LENGTH_SHORT).show();
}
}

Alarm keeps playing after onPause called

Here's code for a timer that plays a sound once it reaches 0 (timer works fine). The problem is the sound persists even through onPause() in MainActivity.java called.
I implemented onDestroy() in SimpleIntentService.java to stop the sound, but apparently it's never called even with finish() in the calling Activity. How am I supposed to make the sound stop when the app is paused?
Here's my MainActivity.java
public class MainActivity extends Activity {
private BroadcastReceiver broadcastReceiver;
NumberPicker picker;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
picker = (NumberPicker) findViewById(minutePicker);
Log.i("TurnToTech", "Project Name - SimpleBackgroundService");
picker.setMinValue(0);
picker.setMaxValue(20);
broadcastReceiver = new BroadcastReceiver(){
#Override
public void onReceive(Context arg0, Intent intent) {
String text = intent.getStringExtra(SimpleIntentService.PARAM_OUT_MSG);
Toast.makeText(getApplicationContext(),
text, Toast.LENGTH_SHORT).show();
}
};
}
Intent msgIntent;
public void startTimer(View view) {
setContentView(R.layout.activity_main);
msgIntent = new Intent(this, SimpleIntentService.class);
msgIntent.putExtra(SimpleIntentService.PARAM_IN_MSG, "Alarm: ");
msgIntent.putExtra("time", picker.getValue());
startService(msgIntent);
}
public void onResume() {
super.onResume();
IntentFilter filter = new IntentFilter(SimpleIntentService.ACTION_RESP);
filter.addCategory(Intent.CATEGORY_DEFAULT);
registerReceiver(broadcastReceiver,filter);
}
public void onPause() {
finish();
unregisterReceiver(broadcastReceiver);
super.onPause();
}
}
And the SimpleIntentService.java
public class SimpleIntentService extends IntentService {
public static final String PARAM_IN_MSG = "in_msg";
public static final String PARAM_OUT_MSG = "out_msg";
int time;
public static final String ACTION_RESP = "org.turntotech.intent.action.MESSAGE_PROCESSED";
public SimpleIntentService() {
super("SimpleIntentService");
}
#Override
protected void onHandleIntent(Intent intent) {
System.out.println("SimpleIntentService Called");
String msg = intent.getStringExtra(PARAM_IN_MSG);
int time = intent.getIntExtra("time", 0);
// Timer implementation
if (time == 0 ){
playSound();
}
while(time > 0){
SystemClock.sleep(5000); // 5 seconds
time -= 5;
String resultTxt = msg + time + " seconds remaining";
Intent broadcastIntent = new Intent();
broadcastIntent.setAction(ACTION_RESP);
broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT);
broadcastIntent.putExtra(PARAM_OUT_MSG, resultTxt);
broadcastIntent.putExtra("time", time);
sendBroadcast(broadcastIntent);
if (time == 0) {
playSound();
}
}
}
Uri alert;
public void playSound(){
alert = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
Ringtone r = RingtoneManager.getRingtone(getApplicationContext(), alert);
r.play();
}
public void onDestroy() {
Ringtone r = RingtoneManager.getRingtone(getApplicationContext(), alert);
r.stop();
super.onDestroy();
}
}
In your IntentService you're not really stopping the same alarm in your onDestroy function. Because each time you're getting a new instance of it.
So I would like to suggest to keep a public static variable of Ringtone so that it can be accessed from everywhere. Declare them in your MainActivity.
public static Ringtone r;
public static Uri alert;
Initialize them in the onCreate function of your MainActivity.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// ... Other statements
// Initialize ringtone here
initializeRingtone();
}
private void initializeRingtone() {
alert = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
r = RingtoneManager.getRingtone(getApplicationContext(), alert);
}
Now the onPause() function of your MainActivity should look like this
public void onPause() {
unregisterReceiver(broadcastReceiver);
r.stop();
super.onPause();
}
And if you want to play the sound after you resume the application from background and then the timer runs out, you might consider doing something like this in the onResume function of your MainActivity
public void onResume() {
super.onResume();
registerReceiver(broadcastReceiver);
initializeRingtone(); // Initialize it again.
}
And the playSound() function in the IntentService might look like this.
public void playSound(){
// Initialize the alert and ringtone again.
MainActivity.alert = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
MainActivity.r = RingtoneManager.getRingtone(getApplicationContext(), alert);
MainActivity.r.play();
}
public void onDestroy() {
MainActivity.r.stop();
super.onDestroy();
}
Hope that helps!

Service starts when I open the activity without reason

I'm using this code:
public class ActivityMain extends Activity {
private static final String TAG = "MainActivity";
private ServiceSpeechRecognition service;
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder binder) {
ServiceSpeechRecognition.MyBinder b = (ServiceSpeechRecognition.MyBinder) binder;
service = b.getService();
Log.e(TAG, "Service connected");
}
public void onServiceDisconnected(ComponentName className) {
savePrefs();
service = null;
Log.e(TAG, "Service disconnected");
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.e(TAG, "onCreate");
setContentView(R.layout.activity_ui_main);
getPackageManager().setComponentEnabledSetting(new ComponentName(this, getPackageName() + ".MainActivity-Alias"), PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
}
#Override
protected void onResume() {
super.onResume();
Log.e(TAG, "onResume");
GoogleSearchApi.registerQueryGroup(this, ReceiverGoogleSearch.group);
// Load prefs
SharedPreferences prefs = ActivityMain.getPrefs(this);
String key_phrase = prefs.getString(Preferences.KEY_PHRASE_KEY, Preferences.DEFAULT_KEY_PHRASE);
boolean require_charge = prefs.getBoolean(Preferences.KEY_REQUIRE_CHARGER, true);
// Update Ui
EditText text = (EditText) findViewById(R.id.key_phrase);
text.setText(key_phrase);
CheckBox checkbox = (CheckBox) findViewById(R.id.require_battery);
checkbox.setChecked(require_charge);
// If should, start intent
if (!require_charge || Util.isCharging(this)) {
bindIntent();
}
}
#Override
protected void onPause() {
if (service != null) {
Log.e(TAG, "Unbind");
unbindService(mConnection);
}
super.onPause();
}
private void bindIntent() {
Log.e(TAG, "Bind intent");
Intent intent = new Intent(this, ServiceSpeechRecognition.class);
startService(intent);
bindService(intent, mConnection, 0);
}
public void setKeyPhrase(View view) {
savePrefs();
if (service != null) {
EditText text = (EditText) findViewById(R.id.key_phrase);
String key_phrase = text.getText().toString();
service.setKeyPhrase(key_phrase);
}
Toast.makeText(this, R.string.str_key_phrase_updated, Toast.LENGTH_SHORT).show();
}
public void setRequireCharge(View view) {
savePrefs();
CheckBox checkbox = (CheckBox) view;
boolean require_charge = checkbox.isChecked();
if (service != null) {
service.setRequiresCharge(require_charge);
} else if (!require_charge || Util.isCharging(this)) {
bindIntent();
}
}
public void savePrefs() {
EditText text = (EditText) findViewById(R.id.key_phrase);
String key_phrase = text.getText().toString();
CheckBox checkbox = (CheckBox) findViewById(R.id.require_battery);
boolean require_charge = checkbox.isChecked();
SharedPreferences.Editor prefs = ActivityMain.getPrefs(this).edit();
prefs.putString(Preferences.KEY_PHRASE_KEY, key_phrase);
prefs.putBoolean(Preferences.KEY_REQUIRE_CHARGER, require_charge);
prefs.commit();
}
public static SharedPreferences getPrefs(Context context) {
return context.getSharedPreferences(Preferences.KEY, Context.MODE_PRIVATE | Context.MODE_MULTI_PROCESS);
}
}
this is an activity in which starts a service.. The problem is that the service starts as soon as the activity it opens. I would create a button or checkbox to start it. But now when I open the activity it starts the service. I didn't write any startService() in the onCreate() method.
Here You Start Your Service in On Resume so Replace
private void bindIntent() {
Log.e(TAG, "Bind intent");
Intent intent = new Intent(this, ServiceSpeechRecognition.class);
startService(intent);
bindService(intent, mConnection, 0);
}
to
private void bindIntent() {
Log.e(TAG, "Bind intent");
Intent intent = new Intent(this, ServiceSpeechRecognition.class);
bindService(intent, mConnection, 0);
}
Put below code in your button click event.
Intent intent = new Intent(this, ServiceSpeechRecognition.class);
startService(intent);
Thats it....

In App Purchases Not Saving Shared Preferences

I have an android application similar to wheel of fortune where users have the option to purchase one consumable, $1000, and two entitlements, where they unlock two images as wheel styles. I am using the Amazon In-App Purchasing API. The user should be able to purchase as many consumables as they want but once they purchase the entitlements the unlocked image should be the only image that they see and they should no longer see the locked image. These in-app purchases work fine the first instance I initiate these purchases.
However, the consumable field will only update once and even though I can still go through the process of completing purchases for the consumable, the text view containing the score, or money, does not update other then that first initial purchase. Also the wheels return to the locked image rather then remaining as the unlocked image despite the fact that when I initiate the purchase for these entitlements I am told that I already own these items. Therefore I believe it may be something to do with my SharedPreferences. In short my purchases update my views once and then never again, however the backend code i.e the responses I receive from the Amazon client when completing purchases are correct. Can anyone see where I have made a mistake? Why does the textView containing the score update on the 1st purchase and never again from then on? Also how do I save the changes toe the wheel style so that when it reopens they no longer have the option to purchase the wheel? I have three classes and have included the code below. All and any help is greatly appreciated.
Game Class
public class Game extends Activity {
private ImageView wheel;
private int rand;
private int[] amounts = {100,650,-1,650,300,-1,800,250,-1,500};
private int score = 0;
private TextView scoreText;
private AnimatorSet set;
protected boolean animationDone = true;
private SharedPreferences prefs;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game);
prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
prefs.registerOnSharedPreferenceChangeListener(prefsChanged);
wheel = (ImageView) findViewById(R.id.imageView1);
scoreText = (TextView) findViewById(R.id.score);
score = prefs.getInt("score", 0);
scoreText.setText("$" + String.valueOf(score));
}
private OnSharedPreferenceChangeListener prefsChanged = new OnSharedPreferenceChangeListener() {
#Override
public void onSharedPreferenceChanged(SharedPreferences prefs,
String key) {
if(key.equals("money") && prefs.getBoolean(key, false)) {
score += 1000;
scoreText.setText("$" + String.valueOf(score));
prefs.edit().putBoolean("money", false);
}
}
};
#Override
protected void onStart() {
super.onStart();
InAppObserver obs = new InAppObserver(this);
PurchasingManager.registerObserver(obs);
}
#Override
protected void onPause() {
if(this.isFinishing())
{
prefs.edit().putInt("score", score).commit();
}
super.onPause();
}
#Override
protected void onStop() {
prefs.edit().putInt("score", score).commit();
super.onStop();
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(resultCode != RESULT_CANCELED) {
String style = data.getStringExtra("wheel");
if(style.equals("camo"))
wheel.setImageResource(R.drawable.camowheel);
if(style.equals("gold"))
wheel.setImageResource(R.drawable.goldwheel);
if(style.equals("normal"))
wheel.setImageResource(R.drawable.wheel);
}
}
public void spinTheWheel(View v) {
if(animationDone) {
wheel.setRotation(0);
rand = (int) Math.round(2000 + Math.random()*360);
set = new AnimatorSet();
set.play(ObjectAnimator.ofFloat(wheel, View.ROTATION, rand));
set.setDuration(2000);
set.setInterpolator(new DecelerateInterpolator());
set.start();
animationDone = false;
set.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
calculateResult();
animationDone = true;
}
});
}
}
private void calculateResult() {
int angle = (int) wheel.getRotation();
angle %= 360;
angle = (int) Math.floor(angle/36);
if(amounts[angle] == -1) {
Intent intent = new Intent(this, GameOver.class);
intent.putExtra("score", score);
prefs.edit().putInt("score", 0).commit();
score = 0;
startActivity(intent);
}
else {
score += amounts[angle];
scoreText.setText("$"+String.valueOf(score));
prefs.edit().putInt("score", 0).commit();
}
}
public void upgradeWheel(View v) {
Intent intent = new Intent(getApplicationContext(), ChangeWheel.class);
startActivityForResult(intent, 1);
}
public void endGame(View v) {
Intent intent = new Intent(getApplicationContext(), GameOver.class);
intent.putExtra("score", score);
prefs.edit().putInt("score", 0).commit();
score = 0;
startActivity(intent);
}
public void addMoney(View v) {
PurchasingManager.initiatePurchaseRequest("money");
}
}
ChangeWheel Class
public class ChangeWheel extends Activity {
private Button buyCamoButton;
private Button buyGoldButton;
private ImageButton goldButton;
private ImageButton camoButton;
private SharedPreferences prefs;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_change_wheel);
prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
prefs.registerOnSharedPreferenceChangeListener(prefsChanged);
buyCamoButton = (Button) findViewById(R.id.buyCamo);
buyGoldButton = (Button) findViewById(R.id.buyGold);
goldButton = (ImageButton) findViewById(R.id.goldButton);
camoButton = (ImageButton) findViewById(R.id.camoButton);
goldButton.setEnabled(false);
camoButton.setEnabled(false);
}
private OnSharedPreferenceChangeListener prefsChanged = new OnSharedPreferenceChangeListener() {
#Override
public void onSharedPreferenceChanged(SharedPreferences prefs,
String key) {
if(key.equals("camo") && prefs.getBoolean(key, false)) {
camoButton.setImageResource(R.drawable.camowheel);
camoButton.setEnabled(true);
buyCamoButton.setVisibility(View.INVISIBLE);
}
else if(key.equals("gold") && prefs.getBoolean(key, false)) {
goldButton.setImageResource(R.drawable.goldwheel);
goldButton.setEnabled(true);
buyGoldButton.setVisibility(View.INVISIBLE);
}
}
};
#Override
protected void onStart() {
super.onStart();
InAppObserver obs = new InAppObserver(this);
PurchasingManager.registerObserver(obs);
}
public void camoClick(View v) {
Intent intent = new Intent(getApplicationContext(), Game.class);
intent.putExtra("wheel", "camo");
setResult(RESULT_OK, intent);
finish();
}
public void goldClick(View v) {
Intent intent = new Intent(getApplicationContext(), Game.class);
intent.putExtra("wheel", "gold");
setResult(RESULT_OK, intent);
finish();
}
public void normalClick(View v) {
Intent intent = new Intent(getApplicationContext(), Game.class);
intent.putExtra("wheel", "normal");
setResult(RESULT_OK, intent);
finish();
}
public void buyCamo(View v) {
String req = PurchasingManager.initiatePurchaseRequest("camo");
prefs.edit().putString(req, "camo").commit();
}
public void buyGold(View v) {
String req = PurchasingManager.initiatePurchaseRequest("gold");
prefs.edit().putString(req, "gold").commit();
}
}
InAppObserver Class
public class InAppObserver extends BasePurchasingObserver {
private SharedPreferences prefs;
public InAppObserver(Activity caller) {
super(caller);
prefs = PreferenceManager.getDefaultSharedPreferences(caller.getApplicationContext());
}
#Override
public void onSdkAvailable(boolean isSandboxMode) {
PurchasingManager.initiatePurchaseUpdatesRequest(Offset.BEGINNING);
}
#Override
public void onPurchaseUpdatesResponse(PurchaseUpdatesResponse res) {
for(String sku : res.getRevokedSkus()) {
prefs.edit().putBoolean(sku, false).commit();
}
switch (res.getPurchaseUpdatesRequestStatus()) {
case SUCCESSFUL:
for(Receipt rec : res.getReceipts()) {
prefs.edit().putBoolean(rec.getSku(), true).commit();
}
break;
case FAILED:
// do something
break;
}
}
#Override
public void onPurchaseResponse(PurchaseResponse res) {
switch(res.getPurchaseRequestStatus()) {
case SUCCESSFUL:
String sku = res.getReceipt().getSku();
prefs.edit().putBoolean(sku, true).commit();
break;
case ALREADY_ENTITLED:
String req = res.getRequestId();
prefs.edit().putBoolean(prefs.getString(req, null), true).commit();
break;
case FAILED:
// do something
break;
case INVALID_SKU:
// do something
break;
}
}
}
It could be that you are not using the same editor.
preferences.edit().putString(PreferenceKey.DISTANCE, distance);
preferences.edit().commit();
two different SharedPreferences.Editors are being returned. Hence the
value is not being committed. Instead, you have to use:
SharedPreferences.Editor spe = preferences.edit();
spe.putString(PreferenceKey.DISTANCE, distance);
spe.commit();
From... SharedPreferences not working across Activities

Categories