Video having problems on my phone in Codename One - codenameone

I have created an app for video demonstration using Codename one. I'm Facing some challenges when I'm running the app on my Google Android Phone as it does not allow a full screen view and also after the video is done playing, it does not go back or restart the video again. Another problem was that I had a button at the bottom at the borderlayout and each time I click the button, it corrupts the video and the video won't play anymore. These are codes used for my demonstration app Demonstration App 1, Demonstration App2 .
#Override
protected void postMain1(Form f) {
final MediaPlayer mp = findMpPresent();
try {
InputStream is = Display.getInstance().getResourceAsStream(getClass(), "/sbuda.mp4");
if (is != null) {
mp.setDataSource(is, "video/mp4", null);
} else {
}
} catch (IOException ex) {
ex.getMessage();
}
}

This is a bit unclear since I can't see the stop/start etc with a GUI builder application.
You can use native on-device controls for playback using setFullScreen. Notice that this works nicely on the device but has no equivalent on the simulator.
Once playback is finished the media no longer exists as your input stream has been depleted. You will need to create a new Media object. You can use the completion callback (the Runnable argument) to detect the end of the media.

Related

How to detect URI activation on a WPF desktop package (WAP) after it has already launched?

I have a WPF desktop application that is MSIX-packaged using a Windows Application Package (WAP) project. I already know how to launch my WPF desktop app the first time using URI activation, by calling AppInstance.GetActivatedEventArgs() and then analyzing the arguments:
if (activatedEventArgs.Kind == ActivationKind.Launch)
{
if (((LaunchActivatedEventArgs)activatedEventArgs).Arguments == "myactivationcode")
// .. do something
}
But if a user runs the URI activation a 2nd time, while my app is already launched, I have learned that a new instance of my app is launched. This doesn't happen with UWP apps, just desktop apps. I can kill the 2nd instance to follow a desired singleton pattern, but what I want is for the first instance of my WPF app to get some event that lets it know to come back into view.
Things I've researched that have no answers that I can see:
How to handle URI activation in a Windows Application Packaging Project?
How can I handle file activation from a WPF app which is running as UWP?
https://learn.microsoft.com/en-us/windows/uwp/launch-resume/handle-uri-activation#step-3-handle-the-activated-event
Does any such API or event exist for URI re-activation? Or do I need to do some other form of IPC, like named pipes or WCF on the 2nd instance of my app? Any help here would be greatly appreciated.
But if a user runs the URI activation a 2nd time, while my app is already launched, I have learned that a new instance of my app is launched.
Whether a second instance is launched depends on the implementation of your custom Main method.
In your second link, there is a link to blog post and a code example that demonstrates how to prevent another instance from being launched.
It uses named pipes to communicate with the already running app instance and passes a serialized IActivatedEventArgs to it:
[STAThread]
static void Main(string[] args)
{
IActivatedEventArgs activatedEventArgs = AppInstance.GetActivatedEventArgs();
using (Mutex mutex = new Mutex(false, AppUniqueGuid))
{
if (mutex.WaitOne(0, false))
{
new Thread(CreateNamedPipeServer) { IsBackground = true }
.Start();
s_application = new App();
s_application.InitializeComponent();
if (activatedEventArgs != null)
s_application.OnProtocolActivated(activatedEventArgs);
s_application.Run();
}
else if (activatedEventArgs != null)
{
//instance already running
using (NamedPipeClientStream namedPipeClientStream
= new NamedPipeClientStream(NamedPipeServerName, AppUniqueGuid, PipeDirection.Out))
{
try
{
namedPipeClientStream.Connect(s_connectionTimeout);
SerializableActivatedEventArgs serializableActivatedEventArgs = Serializer.Serialize(activatedEventArgs);
s_formatter.Serialize(namedPipeClientStream, serializableActivatedEventArgs);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, string.Empty, MessageBoxButton.OK, MessageBoxImage.Error);
}
}
}
}
}
Does any such API or event exist for URI re-activation?
No
Or do I need to do some other form of IPC, like named pipes or WCF on the 2nd instance of my app?
Yes. Again, please refer to the mentioned blog post and accompanied code sample.

Streaming Live audio using Codename One

I am trying to convince a friend of mine to use CN1 as his dev platform for mobile apps. One of the challenges he has brought up is the ability to stream live audio from a radio station using a CN1 app.
I have had a look at the docs and I can see examples of loading media files that are already on the phone, but I cannot see an example of where you point it at a URL and stream live audio.
As you have probably guessed he is interested in developing radio apps for remote radio stations that don't already have their own
Is it possible to do this in CN1?
That's quite possible with CN1 and number of developers have done that in the past.
You can use MediaManager and point it to your remote streaming URL.
Below works for playing an audio file from remote URL and could work for streaming:
Form radio = new Form(new BorderLayout());
Display.getInstance().scheduleBackgroundTask(() -> {
try {
Media audio = MediaManager.createMedia(streamingUrl, false);
audio.prepare();
Display.getInstance().callSerially(() -> {
final MediaPlayer player = new MediaPlayer(audio);
player.setAutoplay(true);
audio.setNativePlayerMode(false);
radio.add(BorderLayout.CENTER, player);
radio.revalidate();
});
} catch (IOException err) {
Log.e(err);
ToastBar.showErrorMessage("Error streaming audio: " + err);
}
});
radio.show();
To avoid this error "Video Playing is not supported on this platform", you have to put true to isVidio parameter like this when handling video stream.
Media audio = MediaManager.createMedia(streamingUrl, true);

Media has stopped working the way it should

I have an app which I made over two years ago which has a list of videos. When one of the list buttons is clicked, the media played full screen. This was working perfectly OK on Android (I have't tried other platforms) until I resubmitted it to the build server on 31-07-2016. After this I noticed that the videos were no longer working full screen.
This month, I resubmitted the app to the build server and now there are a couple of things that don't work. The most noticeable feature is that the video is stretched in portrait mode to fill the form (even without setFullScreen()). The other issue I have noticed is that if I click the back button and play another video, I get the new video and the old video still playing at the side / corner of the screen. I have tried pause() and cleanup() but they seem to have no effect. I have tried adding the Media directly to a Container and using MediaPlayer and found the same issues with both.
try {
((com.codename1.ui.layouts.BorderLayout) getLayout()).setCenterBehavior(com.codename1.ui.layouts.BorderLayout.CENTER_BEHAVIOR_CENTER_ABSOLUTE);
Media media = createMedia(currentExternalContent.getIs(), "video/m4v");
Component videoComponent = media.getVideoComponent();
Container videoContainer = new Container(new com.codename1.ui.layouts.BorderLayout());
videoContainer.addComponent(BorderLayout.CENTER, videoComponent);
addComponent(BorderLayout.CENTER, videoContainer);
revalidate();
media.play();
} catch (IOException ex) {
// Dialog.show("Catch", ex.getMessage(), "OK", "Cancel"); // gives 'read failed: EBADF (Bad file descriptor)'
}
}

Why Doesn't My Component Appear On Top of The HTML Page Or Media Player In Codename One

I've used a media player and I'm trying to do rendering on top of it with progress indication or buttons but the code isn't working.
E.g.:
findInfiniteProgress().setVisible(true);
Timer timer = new Timer();
TimerTask timerTask = new TimerTask() {
#Override
public void run() {
Display.getInstance().callSerially(new Runnable() {
#Override
public void run() {
if(findMediaPlayer().getMedia() != null && findMediaPlayer().getMedia().isPlaying()){
findInfiniteProgress(f).setVisible(false);
}else{
findInfiniteProgress(f).setVisible(true);
}
}
});
}
};
Codename One uses lightweight rendering which means all components are drawn in sequence on a single thread. Native widgets (peers) need to be drawn on the native thread and are always drawn on top, that is the secret to Codname Ones portability explained here.
Common peers in Codename One include: Web browser, media playback & native maps.
The workaround is to use Dialog which is effectively a separate Form so the current peer doesn't really render underneath.

How to open a link in default browser using JavaMe?

Need to be cross-device -working for every mobile manufacturer that gives support to JavaME-
In particular: when the application is open, it redirects to a (cabled) link in the default browser of the mobile device.
Found how to do it in a not mobile Java app, but have not found example for JavaME.
I'm using JavaME, with Sun Java Wireless Tool Kit 2.5.2, and eclipseME.
EDIT:
I'm trying to do:
try {
platformRequest("http://www.stackoverflow.com");
destroyApp(true);
notifyDestroyed();
} catch (ConnectionNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
But not sure about if it will work in all platforms. Also, why the app must be destroyed?
Well, this is how, please read the comments of the code:
// In startApp()
boolean mustExit = false;
try {
/**
* mustExit - Boolean
*
* Some MIDP platforms are more restricted than others.
* For example, some don't support concurrent processing,
* so the MIDlet must exit before the platform can honor
* a service request.
*
* If <true> destroy the app. So the browser
* can start.
*/
mustExit = platformRequest("http://www.stackoverflow.com");
} catch (ConnectionNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(mustExit){
destroyApp(true);
notifyDestroyed();
}
Also, if you are under Linux, you must set a default browser for the emulator. Go to yourPath/Java/lib/system.config and, at the end, add the following line:
# Associate the Mozilla browser with platformRequest() - Linux
com.sun.midp.midlet.platformRequestCommand: /usr/bin/firefox
(could be another browser of course)
Now run it in your emulator.Or create the .jad and .jar an run it in your physical phone.

Resources