VideoView in a live wallpaper? - android

As per other questions android-video-as-a-live-wallpaper, is the only way to play a video in a live wallpaper is to decode it yourself?

Just use MediaPlayer instead of VideoView and use MediaPlayer.setSurface instead of MediaPlayer.setDisplay. If you use setDisplay the MediaPlayer trys to tell the SurfaceHolder to keep the screen on which isn't allowed for LiveWallpapers and will throw an error.
I use WebM/vpx8 video but this should work with whatever MediaPlayer supports (just put the video file in res/raw)
package com.justinbuser.nativecore;
import android.media.MediaPlayer;
import android.service.wallpaper.WallpaperService;
import android.view.SurfaceHolder;
import com.justinbuser.android.Log;
public class VideoWallpaperService extends WallpaperService
{
protected static int playheadTime = 0;
#Override
public Engine onCreateEngine()
{
return new VideoEngine();
}
class VideoEngine extends Engine
{
private final String TAG = getClass().getSimpleName();
private final MediaPlayer mediaPlayer;
public VideoEngine()
{
super();
Log.i( TAG, "( VideoEngine )");
mediaPlayer = MediaPlayer.create(getBaseContext(), R.raw.wallpapervideo);
mediaPlayer.setLooping(true);
}
#Override
public void onSurfaceCreated( SurfaceHolder holder )
{
Log.i( TAG, "onSurfaceCreated" );
mediaPlayer.setSurface(holder.getSurface());
mediaPlayer.start();
}
#Override
public void onSurfaceDestroyed( SurfaceHolder holder )
{
Log.i( TAG, "( INativeWallpaperEngine ): onSurfaceDestroyed" );
playheadTime = mediaPlayer.getCurrentPosition();
mediaPlayer.reset();
mediaPlayer.release();
}
}
}

Short answer is yes. Long answer is http://ikaruga2.wordpress.com/2011/06/15/video-live-wallpaper-part-1/

Just to think outside the box, is it possible to take a working video player and re-parent it under a java window in Android? I have not done this in Linux or Android, but under Windows it is possible to get the window handle of a running application and make it a child of a Java frame, with the result that the other application's window looks like its part of your Java application.

I have tried the Justin Buser solution and it does not work (tested on a API 16 device), have also found a similar code on https://github.com/thorikawa/AndroidExample/tree/master/MovieLiveWallpaper/; it does not work either.
The only solution seems to be to use FFMPEG with NDK. eg : https://github.com/frankandrobot

Related

Why won't my MediaPlayer methods work when moved into a class?

I have some methods to play sounds in MainActivity.
They look like this and they work fine.
public void hydrogen(){
final MediaPlayer mp = MediaPlayer.create(this, R.raw.hydrogen);
mp.start();
}
I thought I'd move them into a class, so I can use the methods in other activities.
This is what I have in the class:
import android.media.MediaPlayer;
public class Sounds {
void hydrogen(){
final MediaPlayer mp = MediaPlayer.create(this, R.raw.hydrogen);
mp.start();
}
}
I get red underlines under "this" and R.raw.hydrogen.
The lines under hydrogen go away when I make the method static, but I can't get rid of the lines under "this".
Does anyone know what I've done wrong?
Problem description is:
Cannot resolve method 'create(com.xxmassdeveloper.lrwhack2.Sounds, int)'
Thanks
First parameter of MediaPlayer.create(Context context, int resid) consumes Context.
If you look into Activity class, it extends Context. Therefore within the functions of your Activity class, you can use this, and it refers to the Activity class you are at.
And for your class Sounds, it is just a simple class without relationship with Context. So you need to pass Context into this class, like following:
public class Sound {
// Create a local variable Context so that you can access it in functions of this Class
private Context context;
// Create a constructor with Context
public Sound(Context context) {
this.context = context;
}
void hydrogen() {
final MediaPlayer mp = MediaPlayer.create(context, R.raw.colors);
mp.start();
}
}
And then you can make use of the passed Context for your function.

Dart: How Can I use multiple instances of the same singleton for different purposes?

I have a class that is used to play sound using audioplayers.I have the below code where the function clickSound just plays a simple button click sound audio without any loop and the function loopSound plays music in a loop.However I am unable to play both at the same time in case the music is playing and I want to click a button for example.How can I implement that functionality with the below code?
import 'package:audioplayers/audioplayers.dart';
import 'package:biblequiz/services/preferences.dart';
class AudioService {
AudioPlayer player = AudioPlayer();
static final AudioService instance = AudioService._();
AudioService._() {
this.player.setVolume(1.0);
}
void clickSound() async {
await player.play(AssetSource('sounds/click.mp3'));
}
void loopSound() async {
player.setReleaseMode(ReleaseMode.loop);
await player.play(AssetSource('sounds/music.wav'));
}
void stopLoop() async {
await player.stop();
}
}
"Multiple singletons" by itself sounds mutually exclusive. While nothing is blocking you from creating another static instance under a different name, in your case, you may want to rethink your app's architecture. For example, you may want to use multiple instances of your AudioService instead of a singleton and inject the necessary instance of that AudioService.

how to implement audio visualizer to exoplayer

I am working on a radio app . I used exoplayer as player on my project and I want to add audio visualizer on my playeractivity . but I couldn't find any tutorial or sample for it . I just made a customeRenderfactory and add it to my player . But I don't know what should I do more ? any help or suggestion ? I should mention my player work fine right now and I just need to find a solution to add visualizer to it .
RenderFactory class :
public class RenderFactory extends DefaultRenderersFactory {
private TeeAudioProcessor.AudioBufferSink listener;
private AudioProcessor[] aMProcessors;
private TeeAudioProcessor teeAudioProcessor;
private AudioRendererEventListener eventListener;
public RenderFactory(Context context, TeeAudioProcessor.AudioBufferSink myListener) {
super(context);
this.listener = myListener;
teeAudioProcessor = new TeeAudioProcessor(this.listener);
}
#Override
protected void buildAudioRenderers(Context context, int extensionRendererMode, MediaCodecSelector mediaCodecSelector, #Nullable DrmSessionManager<FrameworkMediaCrypto> drmSessionManager, boolean playClearSamplesWithoutKeys, boolean enableDecoderFallback, AudioProcessor[] audioProcessors, Handler eventHandler, AudioRendererEventListener eventListener, ArrayList<Renderer> out) {
aMProcessors = new AudioProcessor[]{teeAudioProcessor};
super.buildAudioRenderers(context, extensionRendererMode, mediaCodecSelector, drmSessionManager, playClearSamplesWithoutKeys, enableDecoderFallback, aMProcessors, eventHandler, eventListener, out);
}
}
in my playerActivity I added this code and set renderfactory to my player but nothing happened .
RenderFactory renderFactory = new RenderFactory(this, new TeeAudioProcessor.AudioBufferSink() {
#Override
public void flush(int sampleRateHz, int channelCount, int encoding) {
// what should I add here?
}
#Override
public void handleBuffer(ByteBuffer buffer) {
// what should I add here?
}
});
I tried to followed this tutorial but I wasn't successful.
tutorial
To directly answer your question:
#Override
public void flush(int sampleRateHz, int channelCount, int encoding) {
// you dont have to do anything here
}
#Override
public void handleBuffer(ByteBuffer buffer) {
// This will give you the bytes from the sound that is going to be played
// here you apply FFT so the audio move to the frequency domain instead of time based
}
You can learn more about FFT here
FFT is a well known algorithm, so you may find it implemented on plenty os sites. You can use this library if yout want, but there is standalone codes around.
Once you have the FFT array, you can draw the values in a view.
You can use this guy's code as an example: https://github.com/dzolnai/ExoVisualizer
There's also a blog post he made about it: https://www.egeniq.com/blog/alternative-android-visualizer

Inheritance and MediaPlayer

I have a class called CoordMediaPlayer that inherits from MediaPlayer. My CoordMediaPlayer must be able to use the MediaPlayer methods so It's why I use inheritance...
The problem is that to instanciate a MediaPlayer it must use a MediaPlayer.create() static method. It's not like if it just calls a constructor and then I can use method of the parent class normally. If I inherit from MediaPlayer I can't access to the create() method from a class that inherit MediaPlayer I guess because it's static method, I can't Override it.
In ideal I would want to have my CoordMediaPlayer, this CoordMediaPlayer would not contains a MediaPlayer object but I would be able to call all MediaPlayer methods directly from a CoordMediaPlayer instance. It would be still better if I don't have the same kind of static create() method in my CoordMediaPlayer, this creation would be done when I instanciate my CoordMediaPlayer.
The only one way I found to deal with this, is to have a MediaPlayer object in my CoordMediaPlayer, then my CoordMediaPlayer inherit from MediaPlayer and override all the methods I need just by calling the method of my MediaPlayer object... but that looks kind of weird to me... is there any other way to deal with this kind of situation, without having a MediaPlayer in my CoordMediaPlayer but call directly my inherited MediaPlayer methods ?
This is how I deal with this, my CoordMediaPlayer class inherit from MediaPlayer and at the same time contains an instance of a MediaPlayer and have to override all methods of MediaPlayer I want to use...
Activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
context = getApplicationContext();
int fileResId = context.getResources().getIdentifier("s2", "raw", context.getPackageName());
CoordMediaPlayer cmp = new CoordMediaPlayer(context,fileResId);
cmp.start();
}
CoordMediaPlayer
public class CoordMediaPlayer extends MediaPlayer {
private MediaPlayer mediaPlayer;
private Point coordinates;
#Override
public void start() throws IllegalStateException {
mediaPlayer.start();
}
public CoordMediaPlayer(Context context, int resId) {
mediaPlayer = MediaPlayer.create(context,resId);
}
public void setCoordinates(Point coordinates) {
this.coordinates = coordinates;
}
public Point getCoordinates() {
return coordinates;
}
}
MediaPlayer class actually has public costructor so you don't have to use the create(..) method for contruction. Documentation only suggest to use static methods in some cases.
By the way, the approach you illustrated in your question is called "composition" and is legit and usually thought as better approach than iheritance. Check this stackoverflow response: Prefer composition over inheritance?.
However I'd recomend to think more about reasons, why do you think you need to inherit from the MediaPlayer class, in your case. I honestly think you don't need to and you can just use own class encapsulating MediaPlayer instance and providing it's own api to the rest of your application.

Null pointer dereference of 'object' where null comes from condition in Android

Following class I use to create a MediaPlayer object and. This works fine
import android.content.Context;
import android.media.MediaPlayer;
import android.view.View.OnClickListener;
public class PatientAlarm {
private static MediaPlayer md ;
private PatientAlarm() {
}
private PatientAlarm(Context context) {
md = MediaPlayer.create(context, R.raw.patient_alarm);
md.setLooping(true);
}
public static MediaPlayer getMediaPlayer(Context context) {
if (md == null) {
new PatientAlarm(context);
}
return md;
}
public static void startMediaPlayer(Context context) {
if (md == null) {
new PatientAlarm(context);
md.start();
} else {
if (!md.isPlaying()) {
new PatientAlarm(context);
md.start();
}
}
}
public static void stopMediaPlayer(OnClickListener onClickListener) {
if (md == null) {
} else {
if (md.isPlaying()) {
md.stop();
}
}
}
}
But the problem is Klocwork analyzer says
NPE.COND: Null pointer dereference of 'md' where null comes from condition : Java : PatientAlarm.java : Critical (1) : Analyze : Local
That occurs in below line
md.start();
I have no idea what it does mean. before start md, I check whether it is null.
Please guide me to make my code more reliable and how to solve this issue,
You totally messed up the concept of Object Oriented Programming.
You defined PatientAlarm class to incapsulate all logic of working with MediaPlayer. It's OK.
But why did you make all methods static? Why new PatientAlarm() called inside these methods and created instance even not assigned to some variable or field that makes it target for garbage collection?
This is example of how you should do it:
public class PatientAlarm {
private MediaPlayer md;
public PatientAlarm(Context context) {
md = MediaPlayer.create(context, R.raw.patient_alarm);
md.setLooping(true);
md.prepare();
}
public void start() {
if (!md.isPlaying()) {
md.start();
}
}
public void stop() {
if (md.isPlaying()) {
md.stop();
}
}
}
Adapt it to your case and read more about using MediaPlayer class.
which md.start(); line? there are 2... anyway your code is totally vulnerable for concurrency issues, you may read about locks to prevent it, but I would start form refactoring, before you get into advanced stuff. Creating a new object just to initialize a static member of the class is probably the most ugly approach for singleton I have ever seen.. If you really need to, use static method to do it for you, at least there wont be a new object for GC to collect. But in fact the use of static object in your example seems to be a miss first of all. Try rewriting it without static fields or methods and most likely your code will be simpler and more reliable.

Categories

Resources