Android Media Player returns wrong duration in API level 19 (Kitkat)

  • Thread starter Thread starter Wrichik Basu
  • Start date Start date
  • Tags Tags
    Android
Click For Summary
The discussion centers on the development of an Android app that allows users to set a date and time for media playback using the Android MediaPlayer API. The app features a foreground service that manages countdown and playback without user interaction. Users can interact with a notification to view the remaining time and control playback. The app runs smoothly on API levels 22 and above but encounters issues on API 19, where the media player fails to return the correct duration after being paused. Despite searching for solutions, no effective fixes have been found, and the developer considers dropping support for KitKat (API 19) due to its low user base, which is about 4%. The developer has temporarily set the minimum SDK to 22 but is open to testing on real devices running API 19 to confirm the issue. They are also exploring alternative methods to bypass the problematic API calls.
Wrichik Basu
Science Advisor
Insights Author
Gold Member
Messages
2,180
Reaction score
2,721
I have almost completed my first Android app. It let's the user set a date and time, after which the user picks a media file. The app plays the media when the time comes. The app comes with an inbuilt media player using the Android MediaPlayer API. The countdown and the playback are done in a single foreground service that can run without user interaction once started.

Once the playback starts, the user can tap on the notification to launch an activity that shows the time left for the media to end. The media player can be paused or started from the notification (without requiring to launch the activity).

The service provides a static method for the activity to know the time left:
Java:
public static long getDurationLeft() {
    //Log.e(this.getClass().toString(), "Millis: " + (mediaPlayer.getDuration() - mediaPlayer.getCurrentPosition()));
    return (mediaPlayer.getDuration() - mediaPlayer.getCurrentPosition());
}
And this is how the activity shows the time left:
Java:
private void setTimeLeft() {
    handler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
            Bundle b = msg.getData();
            timeLeftView.setText(b.getString("TextView"));
        }
    };

    Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {
            Looper.prepare();
            Log.e(this.getClass().toString(), "Inside thread: " + Thread.currentThread().getName());
            try {
                while (true) {
                    Message message = Message.obtain();
                    Bundle bundle = new Bundle();
                    if (MahalayaService.mediaPlayer.isPlaying()) {
                        long millis = MahalayaService.getDurationLeft();
                        if (millis > 0) {
                            bundle.putString("TextView", DurationFinder.getDuration(millis, 1, getApplicationContext()));
                        } else {
                            break;
                        }
                        message.setData(bundle);
                        handler.sendMessage(message);
                        try {
                            Thread.sleep(500);
                        } catch (InterruptedException e) {
                            Log.e(this.getClass().toString(), e.getMessage());
                        }
                    } else {
                        //Log.e(this.getClass().toString(), "Millis: paused.");
                    }
                }
            } catch (IllegalStateException ignored) {
            } finally {
                Message message = Message.obtain();
                Bundle bundle = new Bundle();
                bundle.putString("TextView", "Playback complete");
                message.setData(bundle);
                handler.sendMessage(message);
            }
        }

    });

    thread.start();

}
Here, MahalayaService is the name of the service class, and DurationFinder is a class that I have defined.

The app runs perfectly on API 22+. I tested it on an API 29 emulator and API 22 and 23 real phones. There is no problem anywhere. This video shows how the app should work normally (API 23).

On testing on an API 19 emulator, however, I find that the media player starts returning wrong duration once it is paused. See this video demonstrating the error. Notice that once the player is started after a pause, the time remains constant. If I pause it once again and start it, the time spring backs to the total media length.

I searched online if anyone else has faced such a problem, and the answer is yes, though no one has specifically mentioned API 19. StackOverflow has some questions mentioning this issue, but none of the answers worked for me. This answer says that the problem is solved on a real device and happens only on an emulator. But I do not have a real device running API 19, nor do I know anyone who has one.

Has anyone here faced this problem? Any known solution (other than changing minSDK to 22)?
 
Technology news on Phys.org
Rather than pursue this error in the OS for 19 perhaps you can find stats on the number of people using that version and then decide if it’s worth pursuing.

Is there any way you can use other v19 api to emulate what you really want it to do and skip calling the problem api?
 
jedishrfu said:
Rather than pursue this error in the OS for 19 perhaps you can find stats on the number of people using that version and then decide if it’s worth pursuing.
When creating a new project in Android Studio, it gives a cumulative distribution chart for the version distribution:

1586935057841.png


From the above, about 4% of the Android phones are Kitkat. If this problem continues, I will have to ditch support for Kitkat and go straight up to Lollipop 5.1. I cannot publish an app to Play Store with a known bug.
jedishrfu said:
Is there any way you can use other v19 api to emulate what you really want it to do and skip calling the problem api?
For my laptop, I can run only x86 and x86-64 system images; other architectures like armeabi-v7a are very slow and not worth spending time on. With this limitation, I tried two out of the two system images available, and both showed the same error. My app should be independent of system architecture, by the way.
 
So you have a problem with a 7-year old version of the operating system emulator. Seems that you have only a small number of choices:
  1. Buy or borrow a real phone and test it
  2. Accept the advice of the internet that this is an emulator-only problem
  3. Declare the 7-year oid OS version unsupported
  4. Require a more recent OS version
 
For the while, I have changed the minSDK to 22 (Nougat). If the current version is successful on PlayStore, then I might roll out a beta version with minSDK 19 and check whether the app actually works. In the meantime, if anyone here has a phone running Kitkat and wants to help me by testing my app, send me a private message.
 
Learn If you want to write code for Python Machine learning, AI Statistics/data analysis Scientific research Web application servers Some microcontrollers JavaScript/Node JS/TypeScript Web sites Web application servers C# Games (Unity) Consumer applications (Windows) Business applications C++ Games (Unreal Engine) Operating systems, device drivers Microcontrollers/embedded systems Consumer applications (Linux) Some more tips: Do not learn C++ (or any other dialect of C) as a...

Similar threads

  • · Replies 1 ·
Replies
1
Views
4K
  • · Replies 6 ·
Replies
6
Views
6K