Android: Alarms and IntentServices - alarmmanager

After lots of research on implementing IntentServices and Alarms together, I've come up with this. I don't know exactly what happens with this code so I need help in knowing exactly what is going on.
public class MainActivity{
//....
public void onNewItemAdded(String[] _entry){
//...
Intent intent = new Intent(MainActivity.this, UpdateService.class);
startService(intent);
}
//....
}
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Intent startIntent = new Intent(context, UpdateService.class);
context.startService(startIntent);
}
public static final String ACTION_REFRESH_ALARM = "com.a.b.ACTION_REFRESH_ALARM";
}
public class UpdateService extends IntentService{
//...
#Override
public void onCreate() {
super.onCreate();
alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
String ALARM_ACTION = AlarmReceiver.ACTION_REFRESH_ALARM;
Intent intentToFire = new Intent(ALARM_ACTION);
alarmIntent = PendingIntent.getBroadcast(this, 0, intentToFire, 0);
}
#Override
protected void onHandleIntent(Intent intent) {
Context context = getApplicationContext();
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(context);
int updateFreq = Integer.parseInt(prefs.getString(
PreferencesActivity.PREF_UPDATE_FREQ, "60"));
boolean autoUpdateChecked = prefs.getBoolean(
PreferencesActivity.PREF_AUTO_UPDATE, false);
if (autoUpdateChecked) {
int alarmType = AlarmManager.ELAPSED_REALTIME_WAKEUP;
long timeToRefresh = SystemClock.elapsedRealtime() + updateFreq
* 60 * 1000;
alarmManager.setInexactRepeating(alarmType, timeToRefresh,
updateFreq * 60 * 1000, alarmIntent);
}
else {
alarmManager.cancel(alarmIntent);
}
refreshKeywords();
}
}
My aim is to get the refreshKeywords() method to be called every minute. Also, what happens if the onNewItemAdded() method is called more than once?
Sorry if this question is stupid, I'm a beginner.

If you wish you to call refreshKeywords()method to be called every minutes why do you use AlarmManager like this,
private void ServiceRunningBackground() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
{
final int restartAlarmInterval = 6000;
final int resetAlarmTimer = 2*1000;
final Intent restartIntent = new Intent(this, MyService.class);
restartIntent.putExtra("ALARM_RESTART_SERVICE_DIED", true);
final AlarmManager alarmMgr = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
Handler restartServiceHandler = new Handler()
{
#Override
public void handleMessage(Message msg) {
PendingIntent pintent = PendingIntent.getService(getApplicationContext(), 0, restartIntent, 0);
alarmMgr.set(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + restartAlarmInterval, pintent);
sendEmptyMessageDelayed(0, resetAlarmTimer);
}
};
restartServiceHandler.sendEmptyMessageDelayed(0, 0);
}
}
Just call this method where ever you want and set the time accordingly

Related

JustMock Arranging a method that returns an object whose value needs to be propagated into the SUT

I feel like I have to be missing something that is obvious, or I am overcomplication what I am doing. I am attempting to test a method that contains several other methods. One method is passed an object to write data to a database, in which the ID will be updated. This ID is then set to a local variable and used in other methods and the return. I can't get my Assert.AreEqual to work because the ID out is always 0 when I expect it to be 12. I have not had a lot of experience with UnitTesting and less with JuskMock. I assume I am doing something wrong.
This simplified pseudo code demonstrates my issue.
public class MyObj: IMyObject
{
public int ID { get; set; }
public string Name {get;set;}
}
public int Query(string Name)
{
int ID = 0;
ID = _setID.FindPerson(Name);
if(ID = 0)
{
IMyObject myObj = new MyObj(0, Name);
_setID.WritePerson(myObj);
ID = myObj.ID;
}
_setID.WriteSomethingElse(ID)
return ID;
}
public delegate void SetIDDelegate<T1, T2>(T1 arg1, T2 arg2);
[TestMethod]
public void TestQuery_ReturnID()
{
IMyObject UTobj = new MyObj {
ID = 12,
msg = string.Empty
};
Mock.Arrange(() => _mockSetID.WritePerson(
Arg.IsAny<IMyObject>(),
))
.DoInstead(new SetIDDelegate<IMyObject, string>
((IMyObject a, string b) =>
{
a = UTobj;
}
)).MustBeCalled();
int IDout = _objProcessObj.Query();
Mock.Assert(_mockSetID);
Assert.AreEqual(UTobj.ID, IDout);
}
I was able to figure out my issue with my UT. I needed to update the object in the delegate, not replace it.
.DoInstead(new SetIDDelegate<IMyObject, string>
((IMyObject a, string b) =>
{
a.ID = UTobj.ID;
}

Accessing retrofit 2 data outside on response?

I am working on two apps, in one of my app "A" i applied retrofit 2.
This was the method i used to retrieve data.
But here in on Response the data retrieved in response body can be set to activity variables and can be used outside this method without getting null values.
public void fetch_information() {
ApiInterface = ApiClient.getApiClient().create(Api.class);
Call<List<City>> call = ApiInterface.GetCities();
call.enqueue(new Callback<List<City>>() {
#Override
public void onResponse(Call<List<City>> call, Response<List<City>> response) {
citylist = new ArrayList<City>();
citylist = response.body();
cities = new String[citylist.size()];
citiesid = new String[citylist.size()];
for (int i = 0; i < citylist.size(); i++) {
cities[i] = citylist.get(i).getCityName();
citiesid[i] = citylist.get(i).getCityId();
}
city_adapter = new ArrayAdapter<String>(Pay_Payment_X.this, android.R.layout.simple_list_item_1, cities);
city_adapter.setDropDownViewResource(R.layout.spinner_dropdown_layout);
City_Spinner.setAdapter(city_adapter);
}
#Override
public void onFailure(Call<List<City>> call, Throwable t) {
Toast.makeText(getApplicationContext(), t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
after applying this method and on debugging this method i will retain values of varaibles "cities" and "citiesid"out side onResponse.
But applying retrofit 2 similarly on another app "B", i did the same thing for retrieving data on different URL.
ApiUtil.getServiceClass().getAllPost().enqueue(new Callback<List<ApiObject>>() {
#Override
public void onResponse(Call<List<ApiObject>> call, Response<List<ApiObject>> response) {
if (response.isSuccessful()) {
List<ApiObject> postList = response.body();
try {
for (int i = 0; i < postList.size(); i++) {
String Name = postList.get(i).getGamesName();
mGamesName.add(Name);
}
} catch (Exception e) {
}
Log.d(TAG, "Returned count " + postList.size());
NewAdapter adapter = new NewAdapter(getApplicationContext(), postList);
recyclerView.setAdapter(adapter);
}
}
#Override
public void onFailure(Call<List<ApiObject>> call, Throwable t) {
//showErrorMessage();
Log.d(TAG, "error loading from API");
}
});
the data is retrievable inside onResponse but outside it shows null.
So here variables are not retaining values.
Why is this happening?
the only thing came to mind is retrieving data can take time while your code lines are being read and finding null values as data has not been received yet.
Also to mention in app "A" the data retrieved is huge but in app "B" only 3 objects with string values.But still in app"A" data is retrievable.
In app 2 did this for resolving my issue.
public void doRequest( final ApiCallback callback){
ApiUtil.getServiceClass().getAllPost().enqueue(new Callback<List<ApiObject>>() {
#Override
public void onResponse(Call<List<ApiObject>> call, Response<List<ApiObject>> response) {
if (response.isSuccessful()) {
List<ApiObject> postList = response.body();
callback.onSuccess(postList);
// apobject =response.body();
if(response.isSuccessful()) {
try {
for (int i = 0; i < postList.size(); i++) {
String Name = postList.get(i).getGamesName().toString();
mGamesName.add(Name);
}
} catch (Exception e) {
}
}
Log.d(TAG, "Returned count " + postList.size());
NewAdapter adapter = new NewAdapter(getApplicationContext(), postList);
recyclerView.setAdapter(adapter);
}
}
#Override
public void onFailure(Call<List<ApiObject>> call, Throwable t) {
//showErrorMessage();
Log.d(TAG, "error loading from API");
}
});
}
pass an interface
public interface ApiCallback{
void onSuccess(List<ApiObject> result);
}
and in on Create view of activity i called this
doRequest(new ApiCallback(){
#Override
public void onSuccess(List<ApiObject> result){
//here i can set variable values
}
});
the only thing came to mind is retrieving data can take time while your code lines are being read and finding null values as data has not been received yet.
That's entirely correct. Your call is finishing after you check the values. I'm going to go on a limb here and say that it's just a coincidence that it works on one app and not in the other (if they are actually doing it the same way)
When you call callback.onSuccess(postList); doesn't seem to be right either, because you haven't checked yet for success. This means that response.body() might be null and response.errorBody() will contain the body of the error.
If you'd move callback.onSuccess inside the if this would be fixed:
if(response.isSuccessful()) {
callback.onSuccess(response.body());
try {
for (int i = 0; i < postList.size(); i++) {
String Name = postList.get(i).getGamesName().toString();
mGamesName.add(Name);
}
} catch (Exception e) {
}
Last but not least, inside the onSuccess method is when you can use your global variables. Maybe it's better to stop using global variables and just use the callback parameters.

Mocking void methods using Mockito

I cannot seem to mock void methods on Mockito. It gives a unfinished stubbing detected here error. Here is my classfile.
package com.twu.biblioteca;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.InputMismatchException;
import java.util.Scanner;
public class BibliotecaApp {
public static class IntegerAsker {
private final Scanner scanner;
private final PrintStream out;
public IntegerAsker(InputStream in, PrintStream out) {
scanner = new Scanner(in);
this.out = out;
}
public int ask(String message) {
out.print(message);
return scanner.nextInt();
}
}
public static int numberOfBooks = 0;
public static class book{
int serialNo;
String name;
String author;
int publication;
int checkoutstatus;
book(){
serialNo = -1;
name = null;
author = null;
publication = -1;
checkoutstatus = -1;
}
book(int serialNo,String name, String author, int publication){
this.serialNo = serialNo;
this.name = name;
this.author = author;
this.publication = publication;
this.checkoutstatus=checkoutstatus = 1;
}
}
public static int getBoundIntegerFromUser(IntegerAsker asker,String message,int lowerBound,int upperBound) {
int input;
try
{
input = asker.ask(message);
while(input>upperBound || input<lowerBound)
input = asker.ask("Select a valid option! ");
return input;
}
catch(InputMismatchException exception)
{
System.out.print("You have selected an invalid option! ");
}
return -1;
}
public static book[] booksList = new book[20];
public static String welcome(){
IntegerAsker asker = new IntegerAsker(System.in,System.out);
return "**** Welcome Customer! We are glad to have you at Biblioteca! ****";
}
public static void addBooks(){
book newBook1 = new book(1,"Head First Java","Bert Bates",2014);
booksList[1] = newBook1;
numberOfBooks += 1;
book newBook2 = new book(2,"1000 IT Quizzes","Dheeraj Malhotra",2009);
booksList[2] = newBook2;
numberOfBooks += 1;
book newBook3 = new book(3,"100 Shell Programs in Unix","Shivani Jain",2009);
booksList[3] = newBook3;
numberOfBooks += 1;
}
public static void mainMenu(IntegerAsker asker){
System.out.println("1 " + "List Books");
System.out.println("2" + " Checkout a Book");
System.out.println("3 " + "Quit");
int n = getBoundIntegerFromUser(asker,"Enter your choice. ",1,3);
mainMenuaction(n,asker);
}
public static void mainMenuaction(int n,IntegerAsker asker){
if(n==1){
showBooks();
mainMenu(asker);
}
else if(n==2){
checkout(asker);
}
else if(n==3){
return;
}
}
public static void showBooks(){
for(int i=1;i<=numberOfBooks;i++){
if(booksList[i].checkoutstatus!=0)
System.out.println(booksList[i].serialNo + ".\t" + booksList[i].name + "\t" + booksList[i].author + "\t" + booksList[i].publication);
}
}
public static void checkout(IntegerAsker asker){
int Input = asker.ask("Enter the serial numebr of the book that you want to checkout");
if(booksList[Input]!=null){
if(booksList[Input].checkoutstatus!=0){
booksList[Input].checkoutstatus=0;
System.out.println("Thank you! Enjoy the book");
}
else{
System.out.println("That book is not available.");
}
}
else{
System.out.println("That book is not available.");
}
mainMenu(asker);
}
public static void main(String[] args) {
System.out.println(welcome());
addBooks();
IntegerAsker asker = new IntegerAsker(System.in,System.out);
mainMenu(asker);
}
}
And here goes my test file -
package com.twu.biblioteca;
import org.mockito.Mockito;
import org.mockito.Mockito.*;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.*;
public class ExampleTest {
BibliotecaApp test = Mockito.mock(BibliotecaApp.class);
#Test
public void welcometest() {
assertEquals("**** Welcome Customer! We are glad to have you at Biblioteca! ****",test.welcome());
}
#Test
public void addBooksTest(){
test.addBooks();
assertEquals("Head First Java",test.booksList[1].name);
assertEquals("Dheeraj Malhotra",test.booksList[2].author);
assertEquals(2009,test.booksList[3].publication);
}
#Test
public void getBoundIntegerFromUserTest(){
BibliotecaApp.IntegerAsker asker = mock(BibliotecaApp.IntegerAsker.class);
when(asker.ask("Enter your choice. ")).thenReturn(99);
when(asker.ask("Select a valid option! ")).thenReturn(1);
BibliotecaApp.getBoundIntegerFromUser(asker,"Enter your choice. ",1,2);
verify(asker).ask("Select a valid option! ");
}
#Test
public void mainMenuTest(){
BibliotecaApp.IntegerAsker asker = mock(BibliotecaApp.IntegerAsker.class);
when(asker.ask("Enter your choice. ")).thenReturn(3);
test.mainMenu(asker);
verify(test).mainMenuaction(1,asker);
}
#Test
public void checkoutTest(){
BibliotecaApp.IntegerAsker asker = mock(BibliotecaApp.IntegerAsker.class);
BibliotecaApp test = new BibliotecaApp();
BibliotecaApp mock = spy(test);
when(asker.ask("Enter the serial numebr of the book that you want to checkout")).thenReturn(2);
Mockito.doNothing().when(mock).mainMenu(asker);
test.addBooks();
test.checkout(asker);
assertEquals(0,test.booksList[2].checkoutstatus);
}
}
Can someone point out what I am doing wrong please ?
/* system */ public static void mainMenu(IntegerAsker asker){ ... }
/* test */ Mockito.doNothing().when(mock).mainMenu(asker);
Your problem isn't about mocking void methods, it's about mocking static methods, which Mockito can't do. Behind the scenes, Mockito is creating an override of your mocked/spied class (BibliotecaApp) to override each of the methods, but because static methods can't be overridden the same way, Mockito can't change mainMenu's behavior—even just to detect that you called it in the stubbing, which is why this shows up as "unfinished stubbing".
Remove the static modifier from mainMenu and you'll be over that hurdle.
Side note: You also spy on a class but keep the original around. This isn't a good idea in Mockito: A spy actually creates a copy of the object, so if you're relying on behavior that applies to the spy, you'll have to call the test methods on the spy. (This is part of the reason to avoid spies in your tests: using spies can blur the line between testing your system's behavior and testing Mockito's behavior.)
BibliotecaApp test = new BibliotecaApp();
BibliotecaApp mock = spy(test);
when(asker.ask("...")).thenReturn(2);
Mockito.doNothing().when(mock).mainMenu(asker);
test.addBooks(); // should be: mock.addBooks()
test.checkout(asker); // should be: mock.checkout(asker)

JavaFX - bind property to properties of every element in observable Collection

Does exist any method which bind BooleanProperty to conjunction of every element in ObservableList?
ObservableList<BooleanProperty> list;
list = FXCollections.observableList(new ArrayList<BooleanProperty>));
BooleanProperty emptyProperty = new SimpleBooleanProperty();
emptyProperty.bind(Bindings.conunction(list));`
Is there such a method as:
static BooleanBinding conjunction(ObservableList<BooleanProperty> op)
There is no conjunction api defined in the JavaFX 2.2 platform.
You could create a ConjunctionBooleanBinding (aka AllTrueBinding) by subclassing BooleanBinding.
Accept the ObservableList in the constructor of your new class, and use the low level binding api in an overridden computeValue method to set the binding value based upon logically anding together all of the boolean values in the list.
Here is a sample implementation. The sample could be further performance optimized and make use of WeakReferences, so it does not require manual disposition.
import javafx.beans.binding.BooleanBinding;
import javafx.beans.property.BooleanProperty;
import javafx.collections.*;
public class AllTrueBinding extends BooleanBinding {
private final ObservableList<BooleanProperty> boundList;
private final ListChangeListener<BooleanProperty> BOUND_LIST_CHANGE_LISTENER =
new ListChangeListener<BooleanProperty>() {
#Override public void onChanged(
ListChangeListener.Change<? extends BooleanProperty> change
) {
refreshBinding();
}
};
private BooleanProperty[] observedProperties = {};
AllTrueBinding(ObservableList<BooleanProperty> booleanList) {
booleanList.addListener(BOUND_LIST_CHANGE_LISTENER);
boundList = booleanList;
refreshBinding();
}
#Override protected boolean computeValue() {
for (BooleanProperty bp: observedProperties) {
if (!bp.get()) {
return false;
}
}
return true;
}
#Override public void dispose() {
boundList.removeListener(BOUND_LIST_CHANGE_LISTENER);
super.dispose();
}
private void refreshBinding() {
super.unbind(observedProperties);
observedProperties = boundList.toArray(new BooleanProperty[0]);
super.bind(observedProperties);
this.invalidate();
}
}
And here is a test harness to demonstrate how it works:
import java.util.*;
import javafx.beans.property.*;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
public class ListBindingTest {
final BooleanProperty a = new SimpleBooleanProperty(true);
final BooleanProperty b = new SimpleBooleanProperty(true);
final BooleanProperty c = new SimpleBooleanProperty(true);
final BooleanProperty d = new SimpleBooleanProperty(true);
final ObservableList<BooleanProperty> booleanList =
FXCollections.observableArrayList(a, b, c, d);
public static void main(String[] args) {
new ListBindingTest().test();
}
private void test() {
AllTrueBinding at = new AllTrueBinding(booleanList);
System.out.println(at.get() + forArrayString(booleanList));
b.set(false);
System.out.println(at.get() + forArrayString(booleanList));
b.set(true);
System.out.println(at.get() + forArrayString(booleanList));
booleanList.add(new SimpleBooleanProperty(false));
System.out.println(at.get() + forArrayString(booleanList));
booleanList.remove(3, 5);
System.out.println(at.get() + forArrayString(booleanList));
at.dispose();
}
private String forArrayString(List list) {
return " for " + Arrays.toString(list.toArray());
}
}
You can easily implement the method as follows:
public static BooleanBinding conjunction(ObservableList<BooleanProperty> list){
BooleanBinding and = new SimpleBooleanProperty(true).and(list.get(0));
for(int i = 1; i < list.size(); i++){
and = and.and(list.get(i));
}
return and;
}

Adding Scaletempo to a playbin with Vala

I'm having trouble trying to use scaletempo with a playbin in Vala. I've created the playbin, and then created a bin to store the additional plugins swapping out the default audio sink. The example below I grabbed from pyTranscribe and converted to Vala but the Element.link_many is causing an error and I'm not quite sure why.
Am I going about this the right way? Does anybody have any other suggestions?
/* SoundPlayerBackend.vala */
/* Modified code from Damien Radtke's site. http://damienradtke.org/ */
using Gst;
public class SoundPlayerBackend {
//Constants
const double PLAYBACK_RATE_MODIFIER = 2.0;
const int SEEK_SECONDS = 10;
// Method delegates for notifying SoundPlayer about certain events
protected delegate void NotifyEos();
protected delegate void NotifyError(string message);
// Pointer to our EOS delegate
protected NotifyEos on_eos;
// Pointer to our Error delegate
protected NotifyError on_error;
public static void main(string[] args){
var soundplayer = new SoundPlayerBackend();
Gst.init(ref args);
soundplayer.setUri("file:///home/codenomad/Desktop/player-project/hurricane.mp3");
soundplayer.play();
string stop = stdin.read_line ();
while (stop != "stop") {
if (stop == "pause") { soundplayer.pause(); }
else if (stop == "play") { soundplayer.play(); }
stop = stdin.read_line ();
}
}
// Read-only reference to the current sound object
public dynamic Element sound { get; private set; }
// Read-only "is playing" property
public bool is_playing { get; private set; default = false; }
// Read-only "rate" property
public double rate { get; private set; default = 1; }
public void setUri(string uri) {
// Make sure any existing allocated resources are freed
if (sound != null)
sound.set_state(Gst.State.NULL);
sound = ElementFactory.make("playbin2", "playbin");
sound.uri = uri;
var audiobin = new Bin("audioline");
var scaletempo = ElementFactory.make("scaletempo", "scaletempo");
var convert = ElementFactory.make("audioconvert", "convert");
var resample = ElementFactory.make("audioresample", "resample");
var audiosink = ElementFactory.make("autoaudiosink", "audiosink");
audiobin.add_many(scaletempo, convert, resample, audiosink);
//edited based on comment below
//Element.link_many(scaletempo, convert, resample, audiosink);
scaletempo.link_many(convert, resample, audiosink);
var pad = scaletempo.get_pad("sink");
audiobin.add_pad(new GhostPad("sink", pad));
sound.set_property("audio-sink", audiobin);
sound.get_bus().add_watch(on_event);
}
// Play the sound
public void play() {
sound.set_state(State.PLAYING);
print("Playing\n");
is_playing = true;
}
// Pause it
public void pause() {
sound.set_state(State.PAUSED);
is_playing = false;
print("Paused\n");
}
// Event bus, listens for events and responds accordingly
protected bool on_event(Gst.Bus bus, Message message) {
switch (message.type) {
case MessageType.ERROR:
GLib.Error err;
string debug;
sound.set_state(Gst.State.NULL);
is_playing = false;
message.parse_error(out err, out debug);
on_error(err.message);
break;
case MessageType.EOS:
sound.set_state(Gst.State.READY);
is_playing = false;
on_eos();
break;
default:
break;
}
return true;
}
}
I tried using the same code making everything static and received the same outcome/error below:
SoundPlayerBackend.vala:121.9-121.67: error: Access to instance member `Gst.Element.link_many' denied
Element.link_many(scaletempo, convert, resample, audiosink);
Thanks in advance!
That line should read
scaletempo.link_many(convert, resample, audiosink);