Welcome! Log In Create A New Profile

Advanced

[WM19] Android Alarmmanager and BroadcastReceiver do not work ?

Posted by Danny Lauwers 
Danny Lauwers
[WM19] Android Alarmmanager and BroadcastReceiver do not work ?
November 19, 2014 02:55PM
Hi all,

I am trying to use the Android Alarmmanager to set an Intent to check and if not running start my Windev Mobile application again so that it keeps running even when closed by user or Android system. Only when they logoff the application is actualy closed.

I have created the following Java code:

public static void JKeepAliveAlarm()
{
	try {
		AlarmManager alarm;
		Calendar cal;
		PendingIntent alarmIntent;
		
		// Retrieve the current activity
		Activity tmpActivity = getCurrentActivity();
		
		// Retrieve the current Context
		Context tmpContext = getApplicationContext();
		
		cal = Calendar.getInstance();		
		alarm = (AlarmManager)tmpContext.getSystemService(tmpContext.ALARM_SERVICE);
		Intent myIntent = new Intent(tmpContext,AlarmReceiver.class);
		alarmIntent = PendingIntent.getBroadcast(tmpContext, 0, myIntent, 0);

		// Start every 30 seconds
		alarm.setInexactRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 30*1000, alarmIntent); 
		
		Toast.makeText(tmpContext, "Keep Alive Alarm SET", Toast.LENGTH_LONG).show();
	}
	catch(Exception e) {
		e.printStackTrace();
	}
}

I call this from the project code at startup. The toast is displayed so alarm is running.

The Receiverclass is defined as:

public class AlarmReceiver extends BroadcastReceiver {
	
	@Override
	public void onReceive(Context context, Intent intent) {
		
		try {		
			Toast.makeText(context, "Alarm - Start", Toast.LENGTH_LONG).show();
			
			// Try to start the app if not allready running
                        // TODO
			
			Toast.makeText(context, "Alarm  - End", Toast.LENGTH_LONG).show();			
		}
		catch(Exception e) {
			e.printStackTrace();
		}
	}
}

If the alarm would trigger I would see the toast on the screen. But nothing is executed, the receiver is not called ??!

I also added the Receiver to the Manifest:

[attachment 1247 ManifestPart.png]

I checked via the adb shell dumpsys alarm > dump.txt the status of the alarms and the alarm is created and is firing its event.

RTC_WAKEUP #0: Alarm{43854bb0 type 0 com.xxxx.yyyy}

type=0 when=+5s605ms repeatInterval=30000 count=1

operation=PendingIntent{432cadd0: PendingIntentRecord{430215c0 com.xxx.yyyy broadcastIntent}}

+1m38s35ms running, 101 wakeups, 101 alarms: com.xxx.yyyy

cmp={com.xxxx.yyyy/com.xxxx.yyyy.AlarmReceiver}

But my receiver is never called ? :confused:

I tried different names in the Manifest, but nothing seems to work.

I also use the alarmManager for updating the application by running an APK file after the program is closed, and this works fine.

I checked several Android sources on the internet and the basic configuration is in place. Being:
    [*] Create a class AlarmReceiver
    [*] Create a PendingIntent and setup this via the Alarmmanager
    [*] Change the Manifest to define the receiver

Does anybody has a working broadcast receiver in Windev Mobile 19 and can tell me what I am doing wrong ? Maybe there is something missing ?

Hope you can help me !
Thanks
Danny



Edited 1 time(s). Last edit at 11/19/2014 03:05PM by Danny Lauwers.
Attachments:
open | download - ManifestPart.png (2.7 KB)
Hi,

I got the anwser to my own question; after some hours of reseach and testing. smiling smiley

I’ve by chance found how to work with Broadcast receivers. The clue is to use the correct name in the definition of the receiver in the manifest.

When having this class

public static class AlarmReceiver extends BroadcastReceiver {
	
	@Override
	public void onReceive(Context context, Intent intent) {
		
		try {		
			// Retrieve the current Context
			Context tmpContext = getApplicationContext();
			
			Toast.makeText(tmpContext, "test - Start", Toast.LENGTH_LONG).show();
			
			// Stuff todo
			
			Toast.makeText(context, "Awake CareApp - End", Toast.LENGTH_LONG).show();			
		}
		catch(Exception e) {
			e.printStackTrace();
		}
	}
}


And the alarm is triggerd by this

public static void JKeepAliveAlarm()
{
	try {
		AlarmManager alarm;
		Calendar cal;
		PendingIntent alarmIntent;
		
		// Retrieve the current activity
		Activity tmpActivity = getCurrentActivity();
		
		// Retrieve the current Context
		Context tmpContext = getApplicationContext();
		
		cal = Calendar.getInstance();		
		alarm = (AlarmManager)tmpContext.getSystemService(tmpContext.ALARM_SERVICE);
		Intent myIntent = new Intent(tmpContext,AlarmReceiver.class);
		alarmIntent = PendingIntent.getBroadcast(tmpContext, 0, myIntent, 0);

		// Start every 30 seconds
		alarm.setInexactRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 30*1000, alarmIntent); 
		
		Toast.makeText(tmpContext, "Keep Alive Alarm SET", Toast.LENGTH_LONG).show();
	}
	catch(Exception e) {
		e.printStackTrace();
	}
}


The alarm is triggered every 30 seconds and firing the alarm intent.

When defining this in the manifest under the application node

[attachment 1270 manifest2.png]

Will link the alarm correctly to the code to execute.

The problem was that the name must be correct, you have to look inside the android folder where the code is generated and look inside the wdgen folder. And look for your class that contains the AlarmReciever.class code.
This wdgen folder is a deep subfolder of the "Android\Generation" folder under you project folder.

Then you have to build the .wdgen.GWDCPCOL_Java$AlarmReceiver string to match the correct location of your class and use this as the android:name of you receiver node.

!! This is not a Java thing, but a PCSoft Windev Mobile Android thing. Because Windev Mobile compiles the android application in a special way, you need to now the naming convention of PC-Soft in order to set your manifest correctly. I did not found any of this info in the help or on a forum, and this is crucial to get some native android functionality working within your WinDev Mobile Android application.

I have reported this to PC-Soft with the request to include this in the online help.

Once you have the name correct, the broadcast receiver is working. This opens up a lot of Android Native functionality because alot of things are working with broadcastreceivers.

Hope this may help some of you to natively extend there Windev Mobile Android application.
If you do find some interesting Native code that is working with WinDev Mobile Android applications todo some cool stuff, please do share this on the forum as well !

Have a nice day
Danny



Edited 2 time(s). Last edit at 12/10/2014 03:26PM by Danny Lauwers.
Attachments:
open | download - manifest2.png (6.2 KB)
How do you Create The class Java AlarmReceiver in Windev Mobile ?
Hi,

You make global procedures and create a function in it. I Call it "InitClasses", you make this a Java function not a W Language function. (This is in the front of the function header where you see WL or Java, you can click on this to change it.

See: [doc.pcsoft.fr] for more info

Then you make this function completely empty. Then start in the top with writing the needed import statements:

for example:
import java.io.IOException;
import java.io.InputStream;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;

Depending on what android Java functionality you need you need to add the correct imports else you will get a Java compiler error when you create the APK file.

Then you can create classes below the import lines

public static class AlarmReceiver extends BroadcastReceiver {
	
	@Override
	public void onReceive(Context context, Intent intent) {
		
		try {		
			// Retrieve the current Context
			Context tmpContext = getApplicationContext();
			
			//// Do your stuff here		
		}
		catch(Exception e) {
			e.printStackTrace();
		}
	}
}

Depending on the need it has to be static or not. It depends on what class your making etc... Static classes can be used directly without a need for an instance. Other classes need an instance first before you can use them. You have to call some Java code todo this.

If your application is still alive, you could call via CallWLProcedure a WLanguage function todo some stuff. But remember that the alarmReciever will also be run (depending on how you set the alarm) when your application is not running or is destroyed by the system. In that case calling a function from your program does not work. So you have to take care of exceptions and null pointers.

Hope this helps in creating the class.

Danny
Hi,

I insert the imports
import android.content.Context;
import android.content.BroadcastReceiver;
import android.content.Intent;
import android.widget.Toast;
import java.util.Calendar;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.PendingIntent;

But I have
Warning: Parentheses not found
with line

public static class AlarmReceiver extends BroadcastReceiver {
popoy,

This is "normal". Just ignore the warnings if no error occurs at compile time.

I have reported this behavior to PC-Soft

Danny
Does anyone have a working example of working with the Intents. I got a small test app compiled and installed but anytime the phone rings, I get a message stating the "name_of_App" stopped working.

I'm using the static method of defining the Broadcast receiver in the xml file.

Any suggestions?

Thanks,
Ken
Hi Ken,

Could you gives some code to see if we can find the error. I am using intents and Alarmmanager and Broadcastreceivers without problems.

Danny
Hi Danny,

Terribly sorry for the delayed response. The day after I posted the above message, my stink'n macbook OS crashed. Sadly I was unable to restore the images in their entirety, so I had to rebuild both mac and windows from scratch and then restore individual directories / files from the images. Complete PITA, but at least I'm now functional again.

I threw together a quick sample program that I'm testing all this with. It is located at [www.windevtutorials.com]

If you have time to take a look at it I would greatly appreciate it.

Here's what I'm trying to accomplish: I just finished building a nice big workshop for building stuff with wood, metal and electronics (basically a hobby shop). Since I'm going to be spending a fair amount of time in there running loud equipment (table saws, lathes, welders) I built a 1ft by 2ft lighted sign that is driven by an Ardunio and bluetooth. The idea is that when my phone rings or gets an sms message, this light starts flashing and buzzing letting me know somebody is trying to get in touch with me.

Thanks for checking this out. Once I get this figured out I'll put the working example up here for other people.

Thanks,
Ken
Ken,

In order to receive the status of de telephone you have to implement the following function:

public static class PhoneStateMonitor extends PhoneStateListener {
	Context context;
	
	public PhoneStateMonitor(Context context) {
		super();
		// TODO Auto-generated constructor stub
		this.context=context;
		
		Toast.makeText(context, "Init PhoneStateMonitor",Toast.LENGTH_LONG).show();
	}
	
	//This Method Automatically called when changes is detected in Phone State
	
	// Various states are - CALL_STATE_IDLE, CALL_STATE_OFFHOOK, and CALL_STATE_RINGING
	// IDLE             – when there is no incoming call
	// OFFHOOK   		– when the line is busy
	// RINGING      	– when call is incoming
	
	public void onCallStateChanged(int state, String incomingNumber) {
		// TODO Auto-generated method stub
		super.onCallStateChanged(state, incomingNumber);
		
		Toast.makeText(context, "Phone State - "+state+" Incoming Number - "+incomingNumber, Toast.LENGTH_LONG).show();//Giving the Message that Phone State Changed
		//Checking The phone state 
		switch(state)
		{
			case TelephonyManager.CALL_STATE_IDLE: //Phone is in Idle State
			Toast.makeText(context, "Phone State is IDLE", Toast.LENGTH_LONG).show();
			break;
			case TelephonyManager.CALL_STATE_RINGING: //Phone is Ringing
			Toast.makeText(context, "Phone State is RINGING", Toast.LENGTH_LONG).show();
			break;
			case TelephonyManager.CALL_STATE_OFFHOOK: //Call is Received
			Toast.makeText(context, "Call State is OFFHOOK",Toast.LENGTH_LONG).show();
			break;
		}
	}
}

In the Code where the Toast messages are, you need to call WLanguage code via "callWLProcedure" (see details in the help) to be able to keep the status and act on it. Best is not to put long actions in the Listener.

This way you should be able to intercept the telephone calls and display the info on you big display. You can lookup the number that is called in the Android addressbook, and if found you could also display the name.

When writing Java code, be sure to check the needed Android permission because they are not detected automatically like in WLangauge. If you search for "Android PhoneStateListener" you will find extra information about this.

Also look at the Android docs: [developer.android.com]

For handeling the SMS messages you could use the WinDev Mobile SMS functions.

[doc.pcsoft.fr]

Or you have to write some extra Java code to intercept the broadcast intent of the SMS

[developer.android.com]
An Eclipse example is here: [androidexample.com]

Hope this helps you on your way !
In case you don't get it working, let me know and I'll try to help some more.

Success
Danny
Danny, thank you for your sample code. It's perfect for understand this question and it was very useful for my last work smiling smiley

Thank you very much.


Rubén
Ruben Sanchez Peña
Re: [WM19] Android Alarmmanager and BroadcastReceiver do not work ?
September 14, 2016 07:04PM
Hi.

I'm using the codr from this thread to program an allert to tun a global procedude from tha application. This works fine. The alert is fired. Then i want call to a WL procedure with callWLProcedure to run the work.

The problem is when i use CallWLProcedure. The app hang in this line.

How i can call then my global procedure from onReceive?

Thank you

Rubén

/////// Procedure to Alert program
public static void ProgramarAlerta(int nHora, int nMinuto, String sProcedureProgrammingOK, String sProcedureProgrammingError, String sProcedureAlertOK, String sProcedureAlertError)
{
// Se inicializan los nombres de los procedimientos
ProcedureProgrammingOK = sProcedureProgrammingOK;
ProcedureProgrammingError = sProcedureProgrammingError;
ProcedureAlertOK = sProcedureAlertOK;
ProcedureAlertError = sProcedureAlertError;

try {
AlarmManager alarm;
Calendar cal;
PendingIntent alarmIntent;

// Retrieve the current activity
Activity tmpActivity = getCurrentActivity();

// Retrieve the current Context
Context tmpContext = getApplicationContext();

cal = Calendar.getInstance();
cal.setTimeInMillis(System.currentTimeMillis());
cal.set(Calendar.HOUR_OF_DAY, nHora);
cal.set(Calendar.MINUTE, nMinuto);

alarm = (AlarmManager)tmpContext.getSystemService(tmpContext.ALARM_SERVICE);
Intent myIntent = new Intent(tmpContext,AlarmReceiver.class);
alarmIntent = PendingIntent.getBroadcast(tmpContext, 0, myIntent, 0);

// Start every day
alarm.setInexactRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), AlarmManager.INTERVAL_DAY, alarmIntent);

Toast.makeText(tmpContext, "ProcedureProgrammingOK", Toast.LENGTH_LONG).show();
Log.d("boletinesoficiales","Llamando a " + ProcedureProgrammingOK + " en " + Long.toString(cal.getTimeInMillis()));
callWLProcedure(ProcedureProgrammingOK,Long.toString(cal.getTimeInMillis()));
}
catch(Exception e) {
//e.printStackTrace();
Log.e("boletinesoficiales","Error programando la alerta");
Log.e("boletinesoficiales",ProcedureProgrammingError);
callWLProcedure(ProcedureProgrammingError,"");
}
}

///// Class and procedure to receive the broadcast alert

import android.content.*;
import android.app.PendingIntent;
import android.app.AlarmManager;
import android.os.PowerManager;
import android.os.SystemClock;
import android.util.Log;

// Nombre de los procedimientos a llamar
static String ProcedureProgrammingOK; // Programacion OK
static String ProcedureProgrammingError; // Programacion Error
static String ProcedureAlertOK; // Ejecucion de la alerta
static String ProcedureAlertError; // Error de ejecucion


public static class AlarmReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {

try {
// Retrieve the current Context
Context tmpContext = getApplicationContext();

//Toast.makeText(tmpContext, "test - Start", Toast.LENGTH_LONG).show();

// Stuff todo

Toast.makeText(context, "ProcedureAlertOK", Toast.LENGTH_LONG).show();
Log.d("boletinesoficiales","Llamando a " + ProcedureAlertOK);

callWLProcedure(ProcedureAlertOK,""); <<<---------- ERROR
}
catch(Exception e) {
//e.printStackTrace();
Log.e("boletinesoficiales","Error en recepcion de Broadcast");
Log.d("boletinesoficiales",ProcedureAlertError);
//callWLProcedure(ProcedureAlertError,"");
}
}
}
Hello Danny

I am attempting to implement an intent and receive a response from it. I struggled with, and am still struggling with it, catching the response in the "onActivityResult".

Now I am trying to use your method with removing the auto generated static method of WLanguage and doing the following:

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ActivityNotFoundException;
import android.support.annotation.Nullable;
import android.app.Activity;
import android.widget.Toast;

public static class Beta extends Activity{

	Context ctx;
	Context fofo = this;
	Activity act = getCurrentActivity();
	public void find()
	{				
		//Toast.makeText(fofo, "class entered", Toast.LENGTH_SHORT).show();
		//try the variation of touchprovider
		try{
			Intent i = new Intent();
			ComponentName cn = new ComponentName("com.example.provider", "com.example.till.shopper.FindShopperActivity");
			i.putExtra("ByPassAuth", true);
			i.setComponent(cn);
			act.startActivityForResult(i, 10);			
			
		} catch(ActivityNotFoundException e) {
			Intent i = new Intent();
			ComponentName cn = new ComponentName("com.example.provider.debug", "com.example.till.shopper.FindShopperActivity");
			i.setComponent(cn);
			i.putExtra("ByPassAuth", true);
			act.startActivityForResult(i, 10);					
		}
	}
	
	@Override
	public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
		Toast.makeText(ctx, "result", Toast.LENGTH_SHORT).show();
		try{
			//call external global Windev Procedure to check if there is an update
			boolean valReturn = false;
			valReturn = callWLProcedure_boolean("responseEh");
			//success code = 1010
			if(resultCode==1010) {
				
				
				String name = data.getStringExtra("name");
				String shopperSurname = data.getStringExtra("surname");
				String shopperGuid = data.getStringExtra("guid");
				int shopperCashback = data.getIntExtra("cashback", 0);
				
			}
		}catch(Exception e){
			Toast.makeText(ctx, "result error", Toast.LENGTH_SHORT).show();
		}
	}

}

Should you still be available on this platform I would like to talk to you and see if we can possibly come up with a solution.

Regards
MJ
Author:

Your Email:


Subject:


Spam prevention:
Please, enter the code that you see below in the input field. This is for blocking bots that try to post this form automatically. If the code is hard to read, then just try to guess it right. If you enter the wrong code, a new image is created and you get another chance to enter it right.
Message: