I'm developing an application with burning DVD functionality. The IMAPI2 interfaces stack is provided by a COM object, and I've managed to hook into it using com4j. Now the application is able to burn DVD successefully but unfortunately, I'm not able to capture writing-events during burn. I wonder if somebody can take a look on the code and advise how to subsribe to write engine events correctly. When I'm trying to use this code:
IDiscRecorder2 recorder = ClassFactory.createMsftDiscRecorder2();
String recorderUniqueId = dm.item(0);
// initialize disk recorder
recorder.initializeDiscRecorder(recorderUniqueId);
// Define the new disc format and set the recorder
IDiscFormat2Data dataWriter = ClassFactory.createMsftDiscFormat2Data();
dataWriter.recorder(recorder);
// TODO Need subscribe to writeEngine events but getting error
dataWriter.advise(DWriteEngine2Events.class, new DWriteEngine2EventsReceiver());
But here I'm getting an error in runtime:
java.util.concurrent.CompletionException: com4j.ExecutionException: com4j.ComException: 80040200 (Unknown error) : .\invoke.cpp:517
The DWriteEngine2EventsReceiver class is implementation of the DWriteEngine2Events interface:
public class DWriteEngine2EventsReceiver implements DWriteEngine2Events {
#DISPID(7)
#Override
public void update(Com4jObject object, Com4jObject progress) {
System.out.println("DWriteEngine2EventsReceiver.update");
}
#Override
public int getPtr() {
System.out.println("DWriteEngine2EventsReceiver.getPtr()");
return 0;
}
#Override
public long getPointer() {
System.out.println("DWriteEngine2EventsReceiver.getPointer()");
return 0;
}
// all other methods of DWriteEngine2Events COM interface defined similarly
I expected that DWriteEngine2EventsReceiver.update method should receive event notification.
What I'm doing wrong?
PS. here the full method code: https://github.com/vzateychuk/iso-writer/blob/master/desktop/src/main/java/ru/vez/iso/desktop/burn/BurnSrvImpl.java#L101 (exception in line 125)
Related
For research purposes, I'm modifying Android SystemServer code.
What am I trying to accomplish?
Whenever there is a call to SystemServer (Binder server process), I want to know the source of this call on the Binder client process; more specifically - the source in my application (e.g., File, Class, Method, etc..).
For example, consider the following code from my app:
public class ClipboardReaderService extends Service {
private ClipboardManager mClipboardManager;
private ClipboardManager.OnPrimaryClipChangedListener mListener =
new ClipboardManager.OnPrimaryClipChangedListener() {
#Override
public void onPrimaryClipChanged() {
String clipContent = mClipboardManager.getPrimaryClip().
getItemAt(0).getText().toString();
Log.i(TAG, "Clipboard content: " + clipContent);
}
};
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
mClipboardManager = (ClipboardManager)
getSystemService(CLIPBOARD_SERVICE);
mClipboardManager.addPrimaryClipChangedListener(mListener);
return START_STICKY;
}
}
Using Binder, the corresponding function in SystemServer is being called (and this is where my code should go):
public ClipData getPrimaryClip(String pkg) {
synchronized (this) {
if (mAppOps.noteOp(AppOpsManager.OP_READ_CLIPBOARD,
Binder.getCallingUid(), pkg)
!= AppOpsManager.MODE_ALLOWED || isDeviceLocked()) {
return null;
}
// My code goes here - How can I get the caller method?
addActiveOwnerLocked(Binder.getCallingUid(), pkg);
return getClipboard().primaryClip;
}
}
As I explained above, I have the ability to change the code in SystemServer, and I want to extract the origin of the call on the client side.
What i have tried so far?
So far, I've been trying to extract the client call stack because the information I want should be at the bottom of it.
Print the stack using Thread.currentThread().getStackTrace() - of course this doesn't work, since I print the SystemServer's stack, so I don't see the calls made on the clinet side.
Print stack traces for all live threads using getAllStackTraces() - Again, I can't see the client threads since they exist in a separate JVM.
Print the stack in ClipboardManager (i.e., in setPrimaryClip function) - It did print the client call stack as expected. In fact, I can pass the call stack as an additional parameter to SystemServer, but then I will have to do this for each function in each service (e.g., NotificationManager) and I'm looking for a more comprehensive solution.
Get the caller uid using Binder.getCallingPid() and read the stack from /proc/$pid/stack - That didn't work either, since /proc/$pid/stack only shows kernel stacks.
We are using the Ereza CustomActivityOnCrash library to handle unexpected issues with our android app. It's activity offers some debug output which we enable in develop and test builds but disable on production builds. In addition we want to log that information about crash details (log entries, stack trace, error details) in background.
CustomActivityOnCrash offers to call event listeners which sounds convenient. I wanted to implement the interface in our logging service, however I do not understand how I can access the existing information in the crash activity that way. Which puzzles me, cause isn't that a natural expectation?
Basically I need to access public methods of an android activity object from an event listener method that does not get handed over anything. How can I access that activity in the handler method? And how can I get the intent of the activity leading to the crash which is the argument the crash activity expects in those public methods it offers to access the existing information it offers? The examples given in the libraries documentation and those I could find on the internet are trivial, they only dump example strings, not the actual data collected by the library.
This all sounds counter intuitive to me. Which is why I think I generally miss something here. Maybe someone has a short hint for me to bring me on track again. Thanks!
Here is the basics of the LogService implementation I imagine:
...
import cat.ereza.customactivityoncrash.CustomActivityOnCrash;
...
public class LogService
implements CustomActivityOnCrash.EventListener {
private static LogService instance;
...
public void log(LogLevel level, String message) {
....
}
public void logCrashDetails(String activityLog, String stackTrace, String errorDetails) {
String message = String.format(
"--- CRASH REPORT ---\n\n-- Activity log:\n%s\n\n- Stack trace:\n%s\n\nError details:\n%s",
activityLog,
stackTrace,
errorDetails);
log(LogLevel.ERROR, message);
}
....
// CustomActivityOnCrash EventListener interface
#Override
public void onLaunchErrorActivity() {
log(LogLevel.INFO, "COAC: app crashed");
logCrashDetails(
// CustomActivityOnCrash.getActivityLogFromIntent(...some intent...),
// CustomActivityOnCrash.getStackTraceFromIntent(...some intent...),
// CustomActivityOnCrash.getAllErrorDetailsFromIntent(...some intent...)
);
}
#Override
public void onRestartAppFromErrorActivity() {
log(LogLevel.INFO, "COAC: app restarted");
}
#Override
public void onCloseAppFromErrorActivity() {
log(LogLevel.INFO, "COAC: app closed");
}
}
My Jgroups config file contains the protocol/config
<FD timeout="3000" max_tries="3" />
But how do I use this in the Java code. For example, if there is a cluster and when I detect a failure I want to call an external notifier service via a REST call, like /nodeDown/nodeID
I'm not able to find any java code which does this, all I see is message receive and send, is there a way I can implement this?
Thanks
Adding some more info
I have done the step of writing a RecieverAdpater and override the start, stop, send, recieve method. Please find some code here,
public void receive(Message msg) {
JGroupsDataPacket pckt = (JGroupsDataPacket) msg.getObject();
if ( pckt.getCmd().equals("cacheUpdate") ){
int uid = pckt.getAffectedUid();
cacheUpdateRoutine(uid);
}
if ( pckt.getCmd().equals("ack") ){
System.out.println("got the mesaage!");
}
logger.log(LogLevel.ERROR, "received msg from " + msg.getSrc() + ": " + msg.getObject());
}
public void send(JGroupsDataPacket pckt){
Message msg = new Message(null, null, pckt);
msg.setFlag(Message.Flag.RSVP);
try {
channel.send(msg);
} catch (Exception e) {
e.printStackTrace();
}
}
I want to know where should I add code for example to handle the TimeOutException when I'm sending a message with the RSVP flag enabled. Another requirement is to know, which is the Java callback method which is called when SUSPECT(P) is triggered. I want to catch and handle the machine's going down, timout etc.
Is the viewAccepted() the only place where I can handle this? Is there a sample code around this?
Also is http://www.jgroups.org/manual/html/user-channel.html
the section 3. APIs give all java/programmatic things we can do with JGroups.
Thanks again
I found some documentation here, I think this is the class which I'm supposed to override
public interface MembershipListener {
void viewAccepted(View new_view);
void suspect(Object suspected_mbr);
void block();
void unblock();
}
OK, first off, you have a JChannel. You need to use it to register for view callbacks, like this:
JChannel ch;
ch.setReceiver(this);
'this' extends ReceiverAdapter and overrides viewAccepted():
public void viewAccepted(View view) {
// handle new view
}
To determine the members which left between views v1 and v2:
List<Address> left_mbrs=View.leftMembers(v1,v2);
I recently came to a solution which I particularly like and I would like to know if it has a name as a design pattern or whether it can be considered as matching the State pattern. The problem this solution solves is the following (I will use Java as language for the examples):
We have a system that boots and we need different output levels depending on what subsystems have already been initialized.
(WARNING! This is just an example, NOT working code)
Lets say we have: ConsoleTextMsgs, NetworkMsgs and GUIMsgs i/o subsystems represented as homonymous classes. We have also a class named 'System' implementing the booting system.
interface IOSubsystem {
void showMessage(String msg);
}
class ConsoleTextMsgs implements IOSubsystem
{
public ConsoleTextMsgs() { ... };
void showMessage(String msg) {
impPrint((new Date()).toString() + "\t:\t" + msg);
}
private impPrint(String msg) { ... };
}
//`ConsoleTextMsgs`, `NetworkMsgs` and `GUIMsgs`
class NetworkMsgs implements IOSubsystem
{
public NetworkMsgs(IOSubsystem decorated, NetworkService serv)
{
this.decorated = decorated;
...
...
}
void showMessage(String msg) {
send2net((new Date()).toString() + "\t:\t" + msg); //New functionality which uses the NetworkService
decorated.showMessage(msg); //I want the message to by shown at the console too.
}
private send2net(String msg) { ... };
IOSubsystem decorated;
}
//`ConsoleTextMsgs`, `NetworkMsgs` and `GUIMsgs`
class GUIMsgs implements IOSubsystem
{
public GUIMsgs(IOSubsystem decorated, GUIService serv)
{
this.decorated = decorated;
...
...
}
void showMessage(String msg) {
showOnGUI((new Date()).toString() + "\t:\t" + msg); //New functionality which uses the GUIService
decorated.showMessage(msg); //I want the message to by shown at the console too.
}
private showOnGUI(String msg) { ... };
IOSubsystem decorated;
}
NetworkMsgs can't be used until a NetworkService is available and booted as well as GUIMsgs can't be used until the GUIService is ready.
As you can see, it is an incremental output system since whenever I emit the message through the network I want to show it at the console and whenever showing a GUI message I want it to be sent to the network and shown at the console.
However, these systems aren't available at the same time: Console will be available from the beginning whereas NetworkService will take a little longer to be ready and GUIService will be the last to be prepared.
So I have a booting process given by the 'boot' method at 'System' class:
class System
{
public System()
{
...
output = new ConsoleTextMsgs();
...
}
void boot()
{
output.showMessage("Starting system");
...
output.showMessage("Doing some stuff");
...
output.showMessage("Starting network service");
NetworkService nsrv = bootNetwork();
output = new NetworkMsgs(output, nsrv ); // I call it hot swap decoration, how do you call it?
...
...
...
GUIService gsrv = bootGUI();
output = new GUIMsgs(output,gsrv); // Here we are again, does this even have a name?
}
private IOSubsystem output;
}
I think it can be seen as State+Decorator pattern. Many people may be using it and I would like to know if it has a label.
This can certainly work, and it's clearly using a Decorator pattern. And it resembles State somewhat, but in a pretty simple way and not really using some of the features of the pattern.
I don't know of a name for this.
I'd personally be more inclined to use a Composite here, and implement the various other versions of the IOSubsystem without decorating.
If you define your composite with something like:
public class CompositeIOSubsystem implements IOSubsystem {
List<IOSubsystem> subsystems = new ArrayList<IOSubsystem>();
public void showMessage(String msg) {
for (IOSubsystem subsystem: subsystems)
subsystem.showMessage(msg);
}
public void add(IOSubsystem subsystem) {
subsystems.add(subsystem);
}
}
then you don't have to actually "hot-swap" anything, and all the delegation is handled in one place. Simply put an empty composite in place at the start of your boot and add the subsystems to the composite as they become available.
Does someone knows if it is possible to add push notifications(like Amazon Simple Notification Service) in an Android and iOS with RoboVM libGDX projects? And if it is possible, are there any good tutorials or good hints how to implement such things?
I would be happy about every hint how I can implement it.
Hi I know this is an old question but I was struggling to find a solution for this specially for iOS, but I finally found a way. If the explanation below is confusing and you prefer to see an example here is a github repo with a sample project:
Repo GitHub
I only show the code for iOS see the repo for Android.
The idea is simple you need to create a class that handles sending a notification for each platform on each of your projects (Android and iOS) and have it implement an interface called NotificationsHandler.
NotificationsHandler:
public interface NotificationsHandler {
public void showNotification(String title, String text);
}
iOS Adapter:
public class AdapteriOS implements NotificationsHandler {
public AdapteriOS () {
//Registers notifications, it will ask user if ok to receive notifications from this app, if user selects no then no notifications will be received
UIApplication.getSharedApplication().registerUserNotificationSettings(UIUserNotificationSettings.create(UIUserNotificationType.Alert, null));
UIApplication.getSharedApplication().registerUserNotificationSettings(UIUserNotificationSettings.create(UIUserNotificationType.Sound, null));
UIApplication.getSharedApplication().registerUserNotificationSettings(UIUserNotificationSettings.create(UIUserNotificationType.Badge, null));
//Removes notifications indicator in app icon, you can do this in a different way
UIApplication.getSharedApplication().setApplicationIconBadgeNumber(0);
UIApplication.getSharedApplication().cancelAllLocalNotifications();
}
#Override
public void showNotification(final String title, final String text) {
NSOperationQueue.getMainQueue().addOperation(new Runnable() {
#Override
public void run() {
NSDate date = new NSDate();
//5 seconds from now
NSDate secondsMore = date.newDateByAddingTimeInterval(5);
UILocalNotification localNotification = new UILocalNotification();
localNotification.setFireDate(secondsMore);
localNotification.setAlertBody(title);
localNotification.setAlertAction(text);
localNotification.setTimeZone(NSTimeZone.getDefaultTimeZone());
localNotification.setApplicationIconBadgeNumber(UIApplication.getSharedApplication().getApplicationIconBadgeNumber() + 1);
UIApplication.getSharedApplication().scheduleLocalNotification(localNotification);
}
});
}
}
Now by default Libgdx passes your ApplicationListener or Game object to AndroidLauncher and IOSLauncher along with a configuration object. The trick is to pass the class we created earlier to the ApplicationListener so that you can use it inside your Core project. Simple enough:
public class IOSLauncher extends IOSApplication.Delegate {
#Override
protected IOSApplication createApplication() {
IOSApplicationConfiguration config = new IOSApplicationConfiguration();
// This is your ApplicationListener or Game class
// it will be called differently depending on what you
// set up when you created the libgdx project
MainGame game = new MainGame();
// We instantiate the iOS Adapter
AdapteriOS adapter = new AdapteriOS();
// We set the handler, you must create this method in your class
game.setNotificationHandler(adapter);
return new IOSApplication(game, config);
}
public static void main(String[] argv) {
NSAutoreleasePool pool = new NSAutoreleasePool();
UIApplication.main(argv, null, IOSLauncher.class);
pool.close();
}
}
Now that you have a reference to the implementation of NotificationHandler you can simply call it through your Core project.
public class MainGame extends Game {
// This is the notificatino handler
public NotificationHandler notificationHandler;
#Override
public void create () {
// Do whatever you do when your game is created
// ...
}
#Override
public void render () {
super.render();
// This is just an example but you
// can now send notifications in your project
if(condition)
notificationHandler.showNotification("Title", "Content");
}
#Override
public void dispose() {
super.dispose();
}
// This is the method we created to set the notifications handler
public void setNotificationHandler(NotificationHandler handler) {
this.notificationHandler = handler;
}
}
One last thing
If you need to run the Desktop version then you will need to do the same thing for Desktop otherwise you might get errors, it will not do anything on the Desktop, or you can check the platform before calling the method showNotfication. You can clone the repo where I do this:
Repo GitHub
I've never done it myself. But you can use this tutorial to find out how to write Android specific code in your libGDX project. Your Android code could then receive the notifications and trigger a callback in libGDX. I hope this is at least a step in the right direction.
However I' not sure about doing the same for iOS.