I searched and tried different commands but the output is repeated every 60 seconds. I want to repeat every 10 seconds.
I have this code, but the output is not repeated every 10 seconds:
intent = new Intent(this, typeof(MyBroadcastReceiver));
pendingIntent = PendingIntent.GetBroadcast(
this, 280192, intent, PendingIntentFlags.CancelCurrent);
alarmManager = (AlarmManager)GetSystemService(AlarmService);
alarmManager.SetRepeating(AlarmType.RtcWakeup, DateTime.Now.Millisecond, 10 * 1000, pendingIntent);
This code is the same:
alarmManager.SetRepeating(AlarmType.ElapsedRealtime, SystemClock.ElapsedRealtime() , 10 * 1000, pendingIntent);
why?
You could use Foreground Sevice by start a foregroud notification to keep alive when your app is closed.
here is a simple sample you could refer to and add into your projects.
Create a Service :
[Service(Enabled = true)]
public class MyService : Service
{
private Handler handler;
private Action runnable;
private bool isStarted;
private int DELAY_BETWEEN_LOG_MESSAGES = 10000; // set delay as 10s
private int NOTIFICATION_SERVICE_ID = 1001;
private int NOTIFICATION_AlARM_ID = 1002;
private string NOTIFICATION_CHANNEL_ID = "1003";
private string NOTIFICATION_CHANNEL_NAME = "MyChannel";
public override void OnCreate()
{
base.OnCreate();
handler = new Handler();
//here is what you want to do always, i just want to push a notification every 5 seconds here
runnable = new Action(() =>
{
if (isStarted)
{
// handle your logic here
}
});
}
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
if (isStarted)
{
// service is already started
}
else
{
CreateNotificationChannel();
DispatchNotificationThatServiceIsRunning();
handler.PostDelayed(runnable, DELAY_BETWEEN_LOG_MESSAGES);
isStarted = true;
}
return StartCommandResult.Sticky;
}
public override void OnTaskRemoved(Intent rootIntent)
{
//base.OnTaskRemoved(rootIntent);
}
public override IBinder OnBind(Intent intent)
{
// Return null because this is a pure started service. A hybrid service would return a binder that would
// allow access to the GetFormattedStamp() method.
return null;
}
public override void OnDestroy()
{
// Stop the handler.
handler.RemoveCallbacks(runnable);
// Remove the notification from the status bar.
var notificationManager = (NotificationManager)GetSystemService(NotificationService);
notificationManager.Cancel(NOTIFICATION_SERVICE_ID);
isStarted = false;
base.OnDestroy();
}
private void CreateNotificationChannel()
{
//Notification Channel
NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, NOTIFICATION_CHANNEL_NAME, NotificationImportance.Max);
notificationChannel.EnableLights(true);
notificationChannel.EnableVibration(true);
notificationChannel.SetVibrationPattern(new long[] { 100, 200, 300, 400, 500, 400, 300, 200, 400 });
NotificationManager notificationManager = (NotificationManager)this.GetSystemService(Context.NotificationService);
notificationManager.CreateNotificationChannel(notificationChannel);
}
//start a foreground notification to keep alive
private void DispatchNotificationThatServiceIsRunning()
{
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
.SetDefaults((int)NotificationDefaults.All)
.SetSmallIcon(Resource.Drawable.Icon)
.SetVibrate(new long[] { 100, 200, 300, 400, 500, 400, 300, 200, 400 })
.SetSound(null)
.SetChannelId(NOTIFICATION_CHANNEL_ID)
.SetPriority(NotificationCompat.PriorityDefault)
.SetAutoCancel(false)
.SetContentTitle("Mobile")
.SetContentText("My service started")
.SetOngoing(true);
NotificationManagerCompat notificationManager = NotificationManagerCompat.From(this);
StartForeground(NOTIFICATION_SERVICE_ID, builder.Build());
}
//every 5 seconds push a notificaition
private void DispatchNotificationThatAlarmIsGenerated(string message)
{
var intent = new Intent(this, typeof(MainActivity));
intent.AddFlags(ActivityFlags.ClearTop);
var pendingIntent = PendingIntent.GetActivity(this, 0, intent, PendingIntentFlags.OneShot);
Notification.Builder notificationBuilder = new Notification.Builder(this, NOTIFICATION_CHANNEL_ID)
.SetSmallIcon(Resource.Drawable.Icon)
.SetContentTitle("Alarm")
.SetContentText(message)
.SetAutoCancel(true)
.SetContentIntent(pendingIntent);
var notificationManager = (NotificationManager)GetSystemService(NotificationService);
notificationManager.Notify(NOTIFICATION_AlARM_ID, notificationBuilder.Build());
}
}
in your activity :
protected override void OnResume()
{
base.OnResume();
StartMyRequestService();
}
public void StartMyRequestService()
{
var serviceToStart = new Intent(this, typeof(MyService));
StartService(serviceToStart);
}
Related
I’ve got a mobile crossplatform Xamarin.Forms project in which I try to download a file from a Dropbox repository at startup. It’s a tiny json file of less than 50kB. The code operating the Dropbox API call is shared between my Android and my iOS projects, and my Android implementation works as intended. It’s a Task method which I’ll call the downloader here for convenience.
UPDATED: With the iOS version, I can download the file successfully only when calling my downloader’s launcher (which is a also Task) directly from the BackgroundSynchronizer.Launch() method of my only AppDelegate, but not when delegating this call using a timer to call my downloader through a TimerCallback which calls an EventHandler at recurring times.
I can’t figure out why.
The downloader:
public class DropboxStorage : IDistantStoreService
{
private string oAuthToken;
private DropboxClientConfig clientConfig;
private Logger logger = new Logger
(DependencyService.Get<ILoggingBackend>());
public DropboxStorage()
{
var httpClient = new HttpClient(new NativeMessageHandler());
clientConfig = new DropboxClientConfig
{
HttpClient = httpClient
};
}
public async Task SetConnection()
{
await GetAccessToken();
}
public async Task<Stream> DownloadFile(string distantUri)
{
logger.Info("Dropbox downloader called.");
try
{
await SetConnection();
using var client = new DropboxClient(oAuthToken, clientConfig);
var downloadArg = new DownloadArg(distantUri);
var metadata = await client.Files.DownloadAsync(downloadArg);
var stream = metadata?.GetContentAsStreamAsync();
return await stream;
}
catch (Exception ex)
{
logger.Error(ex);
}
return null;
}
UPDATED: The AppDelegate:
using Foundation;
using UIKit;
namespace Izibio.iOS
{
// The UIApplicationDelegate for the application. This class is responsible for launching the
// User Interface of the application, as well as listening (and optionally responding) to
// application events from iOS.
[Register("AppDelegate")]
public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
{
private BackgroundSynchronizer synchronizer = new BackgroundSynchronizer();
//
// This method is invoked when the application has loaded and is ready to run. In this
// method you should instantiate the window, load the UI into it and then make the window
// visible.
//
// You have 17 seconds to return from this method, or iOS will terminate your application.
//
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
global::Xamarin.Forms.Forms.Init();
LoadApplication(new App());
return base.FinishedLaunching(app, options);
}
public override void OnActivated(UIApplication uiApplication)
{
synchronizer.Launch();
base.OnActivated(uiApplication);
}
}
}
EDIT: The intermediary class (which embeds the DownloadProducts function):
public static class DropboxNetworkRequests
{
public static async Task DownloadProducts(IDistantStoreService distantStorage,
IStoreService localStorage)
{
try
{
var productsFileName = Path.GetFileName(Globals.ProductsFile);
var storeDirectory = $"/{Globals.StoreId}_products";
var productsFileUri = Path.Combine(storeDirectory, productsFileName);
var stream = await distantStorage.DownloadFile(productsFileUri);
if (stream != null)
{
await localStorage.Save(stream, productsFileUri);
}
else
{
var logger = GetLogger();
logger.Info($"No file with the uri ’{productsFileUri}’ could " +
$"have been downloaded.");
}
}
catch (Exception ex)
{
var logger = GetLogger();
logger.Error(ex);
}
}
private static Logger GetLogger()
{
var loggingBackend = DependencyService.Get<ILoggingBackend>();
return new Logger(loggingBackend);
}
}
UPDATED: And the failing launcher class (the commented TriggerNetworkOperations(this, EventArgs.Empty);
in the Launch method succeeds in downloading the file) :
public class BackgroundSynchronizer
{
private bool isDownloadRunning;
private IDistantStoreService distantStorage;
private IStoreService localStorage;
private Timer timer;
public event EventHandler SynchronizationRequested;
public BackgroundSynchronizer()
{
Forms.Init();
isDownloadRunning = false;
distantStorage = DependencyService.Get<IDistantStoreService>();
localStorage = DependencyService.Get<IStoreService>();
Connectivity.ConnectivityChanged += TriggerNetworkOperations;
SynchronizationRequested += TriggerNetworkOperations;
}
public void Launch()
{
try
{
var millisecondsInterval = Globals.AutoDownloadMillisecondsInterval;
var callback = new TimerCallback(SynchronizationCallback);
timer = new Timer(callback, this, 0, 0);
timer.Change(0, millisecondsInterval);
//TriggerNetworkOperations(this, EventArgs.Empty);
}
catch (Exception ex)
{
throw ex;
}
}
protected virtual void OnSynchronizationRequested(object sender, EventArgs e)
{
SynchronizationRequested?.Invoke(sender, e);
}
private async void TriggerNetworkOperations(object sender, ConnectivityChangedEventArgs e)
{
if ((e.NetworkAccess == NetworkAccess.Internet) && !isDownloadRunning)
{
await DownloadProducts(sender);
}
}
private async void TriggerNetworkOperations(object sender, EventArgs e)
{
if (!isDownloadRunning)
{
await DownloadProducts(sender);
}
}
private void SynchronizationCallback(object state)
{
SynchronizationRequested(state, EventArgs.Empty);
}
private async Task DownloadProducts(object sender)
{
var instance = (BackgroundSynchronizer)sender;
//Anti-reentrance assignments commented for debugging purposes
//isDownloadRunning = true;
await DropboxNetworkRequests.DownloadProducts(instance.distantStorage, instance.localStorage);
//isDownloadRunning = false;
}
}
I set a logging file to record my application behaviour when trying to download.
EDIT: Here are the messages I get when calling directly TriggerNetworkOperations from the Launch method:
2019-11-12 19:31:57.1758|INFO|xamarinLogger|iZiBio Mobile Launched
2019-11-12 19:31:57.4875|INFO|persistenceLogger|Dropbox downloader called.
2019-11-12 19:31:58.4810|INFO|persistenceLogger|Writing /MAZEDI_products/assortiment.json at /Users/dev3/Library/Developer/CoreSimulator/Devices/5BABB56B-9B42-4653-9D3E-3C60CFFD50A8/data/Containers/Data/Application/D6C517E9-3446-4916-AD8D-565F4C206AF2/Library/assortiment.json
EDIT: And are those I get when launching through the timer and its callback (with a 10 seconds interval for debugging purposes):
2019-11-12 19:34:05.5166|INFO|xamarinLogger|iZiBio Mobile Launched
2019-11-12 19:34:05.8149|INFO|persistenceLogger|Dropbox downloader called.
2019-11-12 19:34:15.8083|INFO|persistenceLogger|Dropbox downloader called.
2019-11-12 19:34:25.8087|INFO|persistenceLogger|Dropbox downloader called.
2019-11-12 19:34:35.8089|INFO|persistenceLogger|Dropbox downloader called.
EDIT: In this second scenario, the launched task event eventually gets cancelled by the OS:
2019-11-13 09:36:29.7359|ERROR|persistenceLogger|System.Threading.Tasks.TaskCanceledException: A task was canceled.
at ModernHttpClient.NativeMessageHandler.SendAsync (System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) [0x002a5] in /Users/paul/code/paulcbetts/modernhttpclient/src/ModernHttpClient/iOS/NSUrlSessionHandler.cs:139
at System.Net.Http.HttpClient.SendAsyncWorker (System.Net.Http.HttpRequestMessage request, System.Net.Http.HttpCompletionOption completionOption, System.Threading.CancellationToken cancellationToken) [0x0009e] in /Users/builder/jenkins/workspace/xamarin-macios/xamarin-macios/external/mono/mcs/class/System.Net.Http/System.Net.Http/HttpClient.cs:281
at Dropbox.Api.DropboxRequestHandler.RequestJsonString (System.String host, System.String routeName, System.String auth, Dropbox.Api.DropboxRequestHandler+RouteStyle routeStyle, System.String requestArg, System.IO.Stream body) [0x0030f] in <8d8475f2111a4ae5850a1c1349c08d28>:0
at Dropbox.Api.DropboxRequestHandler.RequestJsonStringWithRetry (System.String host, System.String routeName, System.String auth, Dropbox.Api.DropboxRequestHandler+RouteStyle routeStyle, System.String requestArg, System.IO.Stream body) [0x000f6] in <8d8475f2111a4ae5850a1c1349c08d28>:0
at Dropbox.Api.DropboxRequestHandler.Dropbox.Api.Stone.ITransport.SendDownloadRequestAsync[TRequest,TResponse,TError] (TRequest request, System.String host, System.String route, System.String auth, Dropbox.Api.Stone.IEncoder`1[T] requestEncoder, Dropbox.Api.Stone.IDecoder`1[T] resposneDecoder, Dropbox.Api.Stone.IDecoder`1[T] errorDecoder) [0x000a5] in <8d8475f2111a4ae5850a1c1349c08d28>:0
at Izibio.Persistence.DropboxStorage.DownloadFile (System.String distantUri) [0x00105] in /Users/dev3/Virtual Machines.localized/shared/TRACAVRAC/izibio-mobile/Izibio/Izibio.Persistence/Services/DropboxStorage.cs:44
2019-11-13 09:36:29.7399|INFO|persistenceLogger|No file with the uri ’/******_products/assortiment.json’ could have been downloaded.
I’ll simply add a last observation: when debugging the DownloadFile Task from the BackgroundSynchronizer, I can reach the call to client.Files.DowloadAsync: var metadata = await client.Files.DownloadAsync(downloadArg);, but I won’t retrieve any return from this await statement.
OK, I finally found a way out of this by replacing the .NET timer by the iOS implementation (NSTimer).
My new code for the BackgroundSynchronizer class:
public class BackgroundSynchronizer
{
private bool isDownloadRunning;
private IDistantStoreService distantStorage;
private IStoreService localStorage;
private NSTimer timer;
public event EventHandler SynchronizationRequested;
public BackgroundSynchronizer()
{
Forms.Init();
isDownloadRunning = false;
distantStorage = DependencyService.Get<IDistantStoreService>();
localStorage = DependencyService.Get<IStoreService>();
Connectivity.ConnectivityChanged += TriggerNetworkOperations;
SynchronizationRequested += TriggerNetworkOperations;
}
public void Launch()
{
try
{
var seconds = Globals.AutoDownloadMillisecondsInterval / 1000;
var interval = new TimeSpan(0, 0, seconds);
var callback = new Action<NSTimer>(SynchronizationCallback);
StartTimer(interval, callback);
}
catch (Exception ex)
{
throw ex;
}
}
protected virtual void OnSynchronizationRequested(object sender, EventArgs e)
{
SynchronizationRequested?.Invoke(sender, e);
}
private async void TriggerNetworkOperations(object sender, ConnectivityChangedEventArgs e)
{
if ((e.NetworkAccess == NetworkAccess.Internet) && !isDownloadRunning)
{
await DownloadProducts();
}
}
private async void TriggerNetworkOperations(object sender, EventArgs e)
{
if (!isDownloadRunning)
{
await DownloadProducts();
}
}
private void SynchronizationCallback(object state)
{
SynchronizationRequested(state, EventArgs.Empty);
}
private async Task DownloadProducts()
{
isDownloadRunning = true;
await DropboxNetworkRequests.DownloadProducts(distantStorage, localStorage);
isDownloadRunning = false;
}
private void StartTimer(TimeSpan interval, Action<NSTimer> callback)
{
timer = NSTimer.CreateRepeatingTimer(interval, callback);
NSRunLoop.Main.AddTimer(timer, NSRunLoopMode.Common);
}
}
Which produces the following logging lines:
2019-11-13 14:00:58.2086|INFO|xamarinLogger|iZiBio Mobile Launched
2019-11-13 14:01:08.5378|INFO|persistenceLogger|Dropbox downloader called.
2019-11-13 14:01:09.5656|INFO|persistenceLogger|Writing /****_products/assortiment.json at /Users/dev3/Library/Developer/CoreSimulator/Devices/****/data/Containers/Data/Application/****/Library/assortiment.json
2019-11-13 14:01:18.5303|INFO|persistenceLogger|Dropbox downloader called.
2019-11-13 14:01:19.2375|INFO|persistenceLogger|Writing /****_products/assortiment.json at /Users/dev3/Library/Developer/CoreSimulator/Devices/****/data/Containers/Data/Application/****/Library/assortiment.json
But I’m still open to an enlighted explanation of the reason why both timers result in such different behaviours.
have used this link for push notification http://rincethomas.blogspot.in/2012/07/push-notification-in-blackberry.html
the code is running fine and i'm receiving push notification in dialog, but instead of showing the default dialog, i have created my own pop up screen to show push message
but i am getting error in my PushMessageReader.java as you can check that in link. here is my PushMessageReader.java code for pop up screen to show push message
public final class PushMessageReader {
// HTTP header property that carries unique push message ID
private static final String MESSAGE_ID_HEADER = "Push-Message-ID";
// content type constant for text messages
private static final String MESSAGE_TYPE_TEXT = "text";
// content type constant for image messages
private static final String MESSAGE_TYPE_IMAGE = "image";
private static final int MESSAGE_ID_HISTORY_LENGTH = 10;
private static String[] messageIdHistory = new String[MESSAGE_ID_HISTORY_LENGTH];
private static byte historyIndex;
private static byte[] buffer = new byte[15 * 1024];
private static byte[] imageBuffer = new byte[10 * 1024];
static Popupscreen popup;
private static String text;
/**
* Utility classes should have a private constructor.
*/
private PushMessageReader() {
popup = new Popupscreen();
}
/**
* Reads the incoming push message from the given streams in the current thread and notifies controller to display the information.
*
* #param pis
* the pis
* #param conn
* the conn
*/
public static void process(PushInputStream pis, Connection conn) {
System.out.println("Reading incoming push message ...");
try {
HttpServerConnection httpConn;
if (conn instanceof HttpServerConnection) {
httpConn = (HttpServerConnection) conn;
} else {
throw new IllegalArgumentException("Can not process non-http pushes, expected HttpServerConnection but have "
+ conn.getClass().getName());
}
String msgId = httpConn.getHeaderField(MESSAGE_ID_HEADER);
String msgType = httpConn.getType();
String encoding = httpConn.getEncoding();
System.out.println("Message props: ID=" + msgId + ", Type=" + msgType + ", Encoding=" + encoding);
boolean accept = true;
if (!alreadyReceived(msgId)) {
byte[] binaryData;
if (msgId == null) {
msgId = String.valueOf(System.currentTimeMillis());
}
if (msgType == null) {
System.out.println("Message content type is NULL");
accept = false;
} else if (msgType.indexOf(MESSAGE_TYPE_TEXT) >= 0) {
// a string
int size = pis.read(buffer);
binaryData = new byte[size];
System.arraycopy(buffer, 0, binaryData, 0, size);
PushMessage message = new PushMessage(msgId, System.currentTimeMillis(), binaryData, true, true );
text = new String( message.getData(), "UTF-8" );
System.out.println("PUSH MESSAGE================ "+text);
try{
/*final Dialog screen = new Dialog(Dialog.D_OK_CANCEL, " "+text,Dialog.OK,
//mImageGreen.getBitmap(),
null, Manager.VERTICAL_SCROLL);*/
final UiEngine ui = Ui.getUiEngine();
Application.getApplication().invokeAndWait(new Runnable() {
public void run() {
NotificationsManager.triggerImmediateEvent(0x749cb23a76c66e2dL, 0, null, null);
ui.pushGlobalScreen(popup, 0, UiEngine.GLOBAL_QUEUE);
}
});
//screen.setDialogClosedListener(new MyDialogClosedListener());
}
catch (Exception e) {
// TODO: handle exception
}
// TODO report message
} else {
System.out.println("Unknown message type " + msgType);
accept = false;
}
} else {
System.out.println("Received duplicate message with ID " + msgId);
}
pis.accept();
} catch (Exception e) {
System.out.println("Failed to process push message: " + e);
}
}
/**
* Check whether the message with this ID has been already received.
*
* #param id
* the id
* #return true, if successful
*/
private static boolean alreadyReceived(String id) {
if (id == null) {
return false;
}
if (Arrays.contains(messageIdHistory, id)) {
return true;
}
// new ID, append to the history (oldest element will be eliminated)
messageIdHistory[historyIndex++] = id;
if (historyIndex >= MESSAGE_ID_HISTORY_LENGTH) {
historyIndex = 0;
}
return false;
}
class Popupscreen extends PopupScreen{
LabelField label = new LabelField("");
ButtonField Okbutn;
public Popupscreen(){
super(new VerticalFieldManager(), Screen.DEFAULT_CLOSE);
Okbutn = new ButtonField("ok",ButtonField.FIELD_HCENTER);
LabelField lbl = new LabelField("SUNRAYS", LabelField.USE_ALL_WIDTH | DrawStyle.HCENTER){
protected void paintBackground(net.rim.device.api.ui.Graphics g)
{
g.clear();
g.getColor();
//g.setColor(Color.WHITESMOKE);
//g.fillRect(0, 0, Display.getWidth(), Display.getHeight());
g.setColor(Color.WHITESMOKE);
}
};
add(lbl);
add(label);
add(Okbutn);
label.setText(text);
Okbutn.setChangeListener(new FieldChangeListener() {
public void fieldChanged(Field field, int context) {
// TODO Auto-generated method stub
close();
}
});
//this.setBackground(BackgroundFactory.createSolidTransparentBackground(Color.WHITE, 80));
// setBorder(BorderFactory.createSimpleBorder(new XYEdges(),Border.STYLE_TRANSPARENT));
}
}
}
I've been reading about Vala over the past couple of days and decided to dive into it and make some Clutter widgets along the way. I'm currently trying to draw a private actor from my custom actor subclass. Here is a simplified version of what I've got so far.
public class MyContainer : Clutter.Actor, Clutter.Container {
private Clutter.Group group;
public MyContainer() {
group = new Clutter.Group();
group.set_parent(this);
}
public void add_actor(Clutter.Actor actor) {
group.add_actor(actor);
actor.show();
set_size(group.width, group.height);
actor_added(actor);
queue_redraw();
}
public void foreach(Clutter.Callback callback) {
group.foreach(callback);
queue_redraw();
}
public override void get_preferred_height(
float for_width,
out float min_height_p,
out float natural_height_p) {
group.get_preferred_height(
for_width,
out min_height_p,
out natural_height_p);
}
public override void get_preferred_width(
float for_height,
out float min_width_p,
out float natural_width_p) {
group.get_preferred_width(
for_height,
out min_width_p,
out natural_width_p);
}
public override void paint() {
group.paint();
}
public void remove_actor(Clutter.Actor actor) {
group.remove_actor(actor);
set_size(group.width, group.height);
actor_removed(actor);
queue_redraw();
}
public void sort_depth_order() {
group.sort_depth_order();
queue_redraw();
}
}
int main(string [] args) {
// Start clutter.
var result = Clutter.init(ref args);
if (result != Clutter.InitError.SUCCESS) {
stderr.printf("Error: %s\n", result.to_string());
return 1;
}
var stage = Clutter.Stage.get_default();
// Build a MyCollection object.
var myc = new MyContainer();
myc.x = 100;
myc.y = 100;
var r1 = new Clutter.Rectangle();
r1.width = 50;
r1.height = 50;
r1.color = Clutter.Color.from_string("rgb(255, 0, 0)");
var t1 = new Clutter.Text();
t1.text = "The red square.";
t1.y = r1.height;
// Build a Group object similar to the previous.
var group = new Clutter.Group();
group.x = 300;
group.y = 100;
var r2 = new Clutter.Rectangle();
r2.width = 50;
r2.height = 50;
r2.color = Clutter.Color.from_string("rgb(255, 0, 0)");
var t2 = new Clutter.Text();
t2.text = "The red square.";
t2.y = r2.height;
// Display.
myc.add_actor(r1);
myc.add_actor(t1);
group.add_actor(r2);
group.add_actor(t2);
stage.add_actor(myc);
stage.add_actor(group);
stage.show_all();
Clutter.main();
return 0;
}
The example paints the group added directly to the stage, but not the group wrapped by the custom collection that is added to the stage. How can I get this to work and what is wrong with the above?
I've been working on ubuntu 11.10 with valac --pkg clutter-1.0 above_code_example.vala.
This answer is from buz on gnome.irc's #clutter room.
The problem is a missing override for the allocate function.
I've add timer to display images in my app.
is there any way to check the timer is running or not.?
after checking , the timer should be cancel using timer.cancel() method.
Pls hlp me.
Blackberry's Timer is very cheesy - it's just like a Runnable with Thread.sleep() inside. Very commonly for Blackberry, it contains lot of crap you don't actually need and doesn't contain things you do need.
I would dump the Timer and make a class specially for my needs:
abstract public class MyTimer extends Thread {
private final Object waitobj = new Object();
private volatile boolean running;
private volatile boolean canceled;
private final long due;
public MyTimer setDelay(long delay) {
long cur = System.currentTimeMillis();
due = cur + delay;
return this;
}
public MyTimer setAlarmTime(long dueTimeMillis) {
due = dueTimeMillis;
return this;
}
synchronized void setIsRunning(boolean running) {
this.running = running;
}
synchronized public boolean isRunning() {
return running;
}
synchronized public void cancel() {
synchronized (waitobj) {
canceled = true;
waitobj.notify();
}
}
public void run() {
setIsRunning(true);
long cur = System.currentTimeMillis();
long sleep = due - cur;
while (sleep > 0) {
synchronized (waitobj) {
waitobj.wait(sleep);
}
if (isCanceled()) return;
cur = System.currentTimeMillis();
sleep = due - cur;
}
alarm();
setIsRunning(false);
}
private boolean isCanceled() {
return canceled;
}
abstract void alarm();
}
Then I would invoke it like this:
timer = new MyTimer() {
void alarm() {
// do cool things
}
};
timer.setDelay(10000).start();
If I need to cancel it I would do it like this:
if (timer.isRunning()) {
timer.cancel();
}
or simply
timer.cancel();
PS: Note volatile and synchronized things in MyTimer class.
You can manage this yourself by recording the timers unique integer and use it later to cancel. I find a useful place to set/cancel this is in the onVisibilityChanged(boolean) override. I'm assuming here your timed images are for animation.
// start
if (renderLoop==-1) renderLoop = UiApplication.getUiApplication().invokeLater( this, 50, true );
// stop
if (renderLoop!=-1)
{
UiApplication.getUiApplication().cancelInvokeLater( renderLoop );
renderLoop = -1;
}
//assumes your screen implements Runnable
public void run() {
// do something cool
}
Assuming that you're programming in Java with Swing, you have a method called isRunning() within the Timer Class.
http://download.oracle.com/javase/7/docs/api/javax/swing/Timer.html#isRunning%28%29
Regards
Actually I want to make an application which will getGlobalEvent and control that event through another custom application. Is there any way to do so. Can i get global event from a particular application? Its like an application which will lock custom application in your blackberry, if you add following application in that locking app list and put password to access then when u try to open that application, it will ask for a password which u set in the locking app.
Common advices
this should be background application
in timer thread check current foreground application
use custom global modal dialog to request password
if password was wrong close app by simulating back key press or move app to background
Checking Application
Have to say, there can be several processes within one application so we will perform check based on module name:
private String getModuleNameByProcessId(int id) {
String result = null;
ApplicationManager appMan = ApplicationManager.getApplicationManager();
ApplicationDescriptor appDes[] = appMan.getVisibleApplications();
for (int i = 0; i < appDes.length; i++) {
if (appMan.getProcessId(appDes[i]) == id) {
result = appDes[i].getModuleName();
break;
}
}
return result;
}
Move application to Background?
Yep, there's no requestBackground() in ApplicationManager... so what you can do is requestForeground() on the next best app which is not on foreground, and this will move active app to background! You can even bring up Home Screen with requestForegroundForConsole():
protected int switchForegroundModule() {
int id = -1;
ApplicationManager appMan = ApplicationManager.getApplicationManager();
ApplicationDescriptor appDes[] = appMan.getVisibleApplications();
for (int i = 0; i < appDes.length; i++) {
if (!appDes[i].getModuleName().equalsIgnoreCase(STR_MODULE_NAME)) {
id = appMan.getProcessId(appDes[i]);
appMan.requestForeground(id);
// give a time to foreground application
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
break;
}
}
return id;
}
Global Dialog
Just to input password you can extend Dialog, it will be easier to consume result:
class PaswordDialog extends Dialog {
private BasicEditField mPwdField = new BasicEditField();
public PaswordDialog() {
super(Dialog.D_OK_CANCEL, "Enter password", Dialog.CANCEL, null,
Dialog.FIELD_HCENTER);
add(mPwdField);
}
public String getPassword() {
return mPwdField.getText();
}
}
And password check will look like:
private boolean checkPassword() {
boolean result = false;
final PaswordDialog pwdDlg = new PaswordDialog();
invokeAndWait(new Runnable() {
public void run() {
Ui.getUiEngine().pushGlobalScreen(pwdDlg, 0,
UiEngine.GLOBAL_MODAL);
}
});
result = ((Dialog.OK == pwdDlg.getSelectedValue()) && pwdDlg
.getPassword().equalsIgnoreCase(STR_PASSWORD));
return result;
}
Put this all together
Sample to block Adress Book App:
public class LockMainApp extends Application {
private static final String STR_MODULE_NAME = "net_rim_bb_addressbook_app";
private static final String STR_PASSWORD = "12345";
int mFGProcessId = -1;
public LockMainApp() {
Timer timer = new Timer();
timer.schedule(mCheckForeground, 1000, 1000);
}
public static void main(String[] args) {
LockMainApp app = new LockMainApp();
app.enterEventDispatcher();
}
TimerTask mCheckForeground = new TimerTask() {
public void run() {
int id = ApplicationManager
.getApplicationManager().getForegroundProcessId();
if (id != mFGProcessId) {
mFGProcessId= id;
String moduleName = getModuleNameByProcessId(mFGProcessId);
if (moduleName.equalsIgnoreCase(STR_MODULE_NAME)) {
if (!checkPassword())
mFGProcessId = switchForegroundModule();
}
}
};
};
}