This bug is only on some devices.
Project scope:
Indoor navigation system used in malls/ships to locate shops.
It uses beacons to locate shops with bluetooth connection. It uses camera to show directions (arrow) image overlays.
In ArCameraActivity, half green screen shows up in camera preview.
code:
import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.hardware.Camera;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.opengl.Matrix;
import android.os.Build;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import dagger.android.support.DaggerAppCompatActivity;
public class ARActivity extends DaggerAppCompatActivity implements SensorEventListener, LocationListener,
ActivityCompat.OnRequestPermissionsResultCallback, ARView {
private static boolean IS_NAVIGATION_CLICKED = false;
#Inject
ARPresenter presenter;
#BindView(R.id.img_clear)
ImageView imgClear;
#BindView(R.id.img_logout)
ImageView imgLogout;
#BindView(R.id.img_map)
ImageView imgMap;
#BindView(R.id.img_navigation)
ImageView imgNavigation;
final static String TAG = "ARActivity";
private SurfaceView surfaceView;
private FrameLayout cameraContainerLayout;
private AROverlayView arOverlayView;
private Camera camera;
private ARCamera arCamera;
private TextView tvCurrentLocation;
private SensorManager sensorManager;
private final static int REQUEST_CAMERA_PERMISSIONS_CODE = 11;
public static final int REQUEST_LOCATION_PERMISSIONS_CODE = 0;
private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 0; // 10 meters
private static final long MIN_TIME_BW_UPDATES = 0;//1000 * 60 * 1; // 1 minute
private LocationManager locationManager;
public Location location;
boolean isGPSEnabled;
boolean isNetworkEnabled;
boolean locationServiceAvailable;
private ScanRegionsService scanRegionsService;
private boolean isBeaconLoaded = false;
// private static GetMallResponse.Data.Mall identifiedMall;
private Dialog dialog = null;
private static final String IMAGE_URL = "http://98.156.231.92/maps/";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ar);
ButterKnife.bind(this);
sensorManager = (SensorManager) this.getSystemService(SENSOR_SERVICE);
cameraContainerLayout = (FrameLayout) findViewById(R.id.camera_container_layout);
surfaceView = (SurfaceView) findViewById(R.id.surface_view);
tvCurrentLocation = (TextView) findViewById(R.id.tv_current_location);
arOverlayView = new AROverlayView(this);
scanRegionsService = new ScanRegionsService(this);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
beginService();
}
}
if (Util.getSelectedShop() != null) {
showLoading();
}
}
private Runnable mRunnable = new Runnable() {
#Override
public void run() {
if (!isBeaconLoaded) {
Log.d(TAG, "run: "+ isBeaconLoaded);
dismissLoading();
if(!isFinishing()) {
new AlertDialog.Builder(ARActivity.this)
.setIcon(android.R.drawable.ic_dialog_alert)
.setTitle("There is no beacon in your surroundings")
.setMessage("Are you sure you want to stop navigation?")
.setPositiveButton("Yes",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Util.setSelectedShop(null);
finish();
}
})
.show();
}
}
}
};
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
for (int i = 0; i < permissions.length; i++) {
if (permissions[i].equalsIgnoreCase(Manifest.permission.ACCESS_FINE_LOCATION) &&
grantResults[i] == PackageManager.PERMISSION_GRANTED) {
beginService();
} else if (permissions[i].equalsIgnoreCase(Manifest.permission.CAMERA) &&
grantResults[i] == PackageManager.PERMISSION_DENIED) {
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
finish();
}
}
}
private void beginService() {
isBeaconLoaded = false;
arOverlayView.registerReceiver();
scanRegionsService.setupSpaces();
scanRegionsService.startScanning();
onMallIdentified(Util.getSelectedMall());
new Handler().postDelayed(mRunnable, 10000);
}
#OnClick(R.id.img_map)
public void onMapClicked() {
arOverlayView.unregisterReceiver();
// Util.getRouteMap().clear();
Util.setSelectedShop(null);
// Intent intent = new Intent(this, MainActivity.class);
// startActivity(intent);
finish();
}
#OnClick(R.id.img_navigation)
public void onNavClicked() {
if (!IS_NAVIGATION_CLICKED) {
IS_NAVIGATION_CLICKED = true;
arOverlayView.showNavigationMap();
imgNavigation.setImageDrawable(getResources().getDrawable(R.drawable.navigation_on));
} else {
IS_NAVIGATION_CLICKED = false;
arOverlayView.hideNavigationMap();
imgNavigation.setImageDrawable(getResources().getDrawable(R.drawable.navigation_off));
}
}
#OnClick(R.id.img_logout)
public void onLogoutClicked() {
new AlertDialog.Builder(this)
.setIcon(android.R.drawable.ic_dialog_alert)
.setTitle("Confirm")
.setMessage("Are you sure you want to logout?")
.setPositiveButton("Yes",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Util.set("authToken", "");
Intent intent = new Intent(ARActivity.this, LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
finish();
}
})
.setNegativeButton("No", null)
.show();
}
#Override
public void onBackPressed() {
if(!((Activity) this).isFinishing()) {
new AlertDialog.Builder(this)
.setIcon(android.R.drawable.ic_dialog_alert)
.setTitle("Confirm")
.setMessage("Are you sure you want to exit the screen?")
.setPositiveButton("Yes",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
})
.setNegativeButton("No", null)
.show();
}
}
#Override
public void onResume() {
super.onResume();
requestLocationPermission();
requestCameraPermission();
registerSensors();
initAROverlayView();
IntentFilter intentFilter = new IntentFilter(ForegroundScanService.ACTION_DEVICE_DISCOVERED);
registerReceiver(scanningBroadcastReceiver, intentFilter);
}
public void showClearMap() {
imgClear.setVisibility(View.VISIBLE);
}
public void hideClearMap() {
imgClear.setVisibility(View.GONE);
}
#OnClick(R.id.img_clear)
public void onClearClicked() {
new AlertDialog.Builder(this)
.setIcon(android.R.drawable.ic_dialog_alert)
.setTitle("Confirm")
.setMessage("Are you sure you want to stop navigation?")
.setPositiveButton("Yes",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Util.setSelectedShop(null);
}
})
.setNegativeButton("No", null)
.show();
}
#Override
public void onPause() {
unregisterReceiver(scanningBroadcastReceiver);
releaseCamera();
super.onPause();
}
public void requestCameraPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
this.checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
this.requestPermissions(new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSIONS_CODE);
} else {
initARCameraView();
}
}
public void requestLocationPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
this.checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
this.requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_LOCATION_PERMISSIONS_CODE);
} else {
initLocationService();
}
}
public void initAROverlayView() {
if (arOverlayView.getParent() != null) {
((ViewGroup) arOverlayView.getParent()).removeView(arOverlayView);
}
cameraContainerLayout.addView(arOverlayView);
}
public void initARCameraView() {
reloadSurfaceView();
if (arCamera == null) {
arCamera = new ARCamera(this, surfaceView);
}
if (arCamera.getParent() != null) {
((ViewGroup) arCamera.getParent()).removeView(arCamera);
}
cameraContainerLayout.addView(arCamera);
arCamera.setKeepScreenOn(true);
initCamera();
}
private void initCamera() {
int numCams = Camera.getNumberOfCameras();
if (numCams > 0) {
try {
camera = Camera.open();
camera.startPreview();
arCamera.setCamera(camera);
} catch (RuntimeException ex) {
Toast.makeText(this, "Camera not found", Toast.LENGTH_LONG).show();
}
}
}
private void reloadSurfaceView() {
if (surfaceView.getParent() != null) {
((ViewGroup) surfaceView.getParent()).removeView(surfaceView);
}
cameraContainerLayout.addView(surfaceView);
}
private void releaseCamera() {
if (camera != null) {
camera.setPreviewCallback(null);
camera.stopPreview();
arCamera.setCamera(null);
camera.release();
camera = null;
}
}
private void registerSensors() {
sensorManager.registerListener(this,
sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR),
SensorManager.SENSOR_DELAY_FASTEST);
}
#Override
public void onSensorChanged(SensorEvent sensorEvent) {
if (sensorEvent.sensor.getType() == Sensor.TYPE_ROTATION_VECTOR) {
float[] rotationMatrixFromVector = new float[16];
float[] projectionMatrix = new float[16];
float[] rotatedProjectionMatrix = new float[16];
SensorManager.getRotationMatrixFromVector(rotationMatrixFromVector, sensorEvent.values);
if (arCamera != null) {
projectionMatrix = arCamera.getProjectionMatrix();
}
Matrix.multiplyMM(rotatedProjectionMatrix, 0, projectionMatrix, 0, rotationMatrixFromVector, 0);
this.arOverlayView.updateRotatedProjectionMatrix(rotatedProjectionMatrix);
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int i) {
//do nothing
}
private void initLocationService() {
if (Build.VERSION.SDK_INT >= 23 &&
ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
try {
this.locationManager = (LocationManager) this.getSystemService(this.LOCATION_SERVICE);
// Get GPS and network status
this.isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
this.isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (!isNetworkEnabled && !isGPSEnabled) {
// cannot get location
this.locationServiceAvailable = false;
}
this.locationServiceAvailable = true;
if (isNetworkEnabled) {
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
if (locationManager != null) {
location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
updateLatestLocation();
}
}
if (isGPSEnabled) {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
if (locationManager != null) {
location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
updateLatestLocation();
}
}
} catch (Exception ex) {
Log.e(TAG, ex.getMessage());
}
}
private void updateLatestLocation() {
if (arOverlayView != null && location != null) {
arOverlayView.updateCurrentLocation(location);
tvCurrentLocation.setText(String.format("lat: %s \nlon: %s \naltitude: %s \n",
location.getLatitude(), location.getLongitude(), location.getAltitude()));
}
}
#Override
public void onLocationChanged(Location location) {
updateLatestLocation();
}
#Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
#Override
public void onProviderEnabled(String s) {
}
#Override
public void onProviderDisabled(String s) {
}
private final BroadcastReceiver scanningBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "onReceive: ");
isBeaconLoaded = true;
String shopname=Util.getSelectedShop().getShopImage();
Toast.makeText(context, "You are in "+shopname, Toast.LENGTH_LONG).show();
int devicesCount = intent.getIntExtra(BackgroundScanService.EXTRA_DEVICES_COUNT, 0);
RemoteBluetoothDevice device = intent.getParcelableExtra(BackgroundScanService.EXTRA_DEVICE);
Log.i("BEACON", String.format("Total discovered devices: %d\n\nLast scanned device:\n%s", devicesCount, device.toString()));
// statusText.setText(String.format("Total discovered devices: %d\n\nLast scanned device:\n%s", devicesCount, device.toString()));
}
};
#Override
public void onMallIdentified(GetMallResponse.Data.Mall mall) {
// identifiedMall = mall;
// Toast.makeText(this, "Identified "+mall.getPropertyName(), Toast.LENGTH_LONG).show();
presenter.loadShops(mall.getId());
presenter.loadRouteBeacons(mall.getId());
}
public void onUnkownPlaceIdentified() {
arOverlayView.registerReceiver();
Toast.makeText(this, "Unknown place identified", Toast.LENGTH_LONG).show();
List<GetRouteBeaconsResponse.Data.Route> floorRoute = new ArrayList<>();
}
#Override
public void onShopLoaded(List<GetShopsResponse.Data.Shop> shops) {
Log.i(TAG, "onShopLoaded");
if (shops.size() > 0) {
Util.shopMap.clear();
Log.i(TAG, "onShopLoaded shops.size " + shops.size());
Util.activeDeviceMap.clear();
for (GetShopsResponse.Data.Shop shop : shops) {
Util.shopMap.put("" + shop.getId(), shop);
if (shop.getAdImage().length() > 0) {
Drawable drbl = Util.promoImageMap.get(IMAGE_URL + shop.getAdImage());
if (drbl == null) {
String imgkey = IMAGE_URL + shop.getAdImage();
drbl = getResources().getDrawable(R.drawable.promo1, null);
Util.promoImageMap.put(imgkey, drbl);
Runnable runnable = new Runnable() {
#Override
public void run() {
try {
Drawable drb2 = drawableFromUrl(imgkey);
Util.promoImageMap.put(IMAGE_URL + shop.getAdImage(), drb2);
} catch (Exception e) {
Log.i(TAG, "Unable to download image");
}
}
};
new Thread(runnable).start();
}
}
}
}
}
#Override
public void onRouteBeaconLoaded(List<GetRouteBeaconsResponse.Data.Route> floors) {
Log.d(TAG, "onRouteBeaconLoaded: ");
Log.i(TAG, "onRouteBeaconLoaded");
// if (floors.size()>0 && Util.getSelectedShop()!=null){
// Log.i(TAG, "onRouteBeaconLoaded floors.size "+floors.size());
// Util.getRouteMap().clear();
// for (GetRouteBeaconsResponse.Data.Route route: floors){
// String comkey = route.proximityUUID+route.major+route.minor;
// Util.getRouteMap().put(comkey, route);
// }
// Util.setSelectedShop(Util.getSelectedShop());
// Log.i(TAG, "onShopLoaded setup space scanRegionsService");
// scanRegionsService.setupSpaces();
// Log.i(TAG, "onShopLoaded startScanning");
// scanRegionsService.startScanning();
// }
if (floors.size() > 0) {
Log.i(TAG, "onRouteBeaconLoaded floors.size " + floors.size());
Util.getRouteMap().clear();
for (GetRouteBeaconsResponse.Data.Route route : floors) {
String comkey = route.proximityUUID + route.major + route.minor;
Util.getRouteMap().put(comkey, route);
}
Log.i(TAG, "onShopLoaded setup space scanRegionsService");
scanRegionsService.setupSpaces();
Log.i(TAG, "onShopLoaded startScanning");
scanRegionsService.startScanning();
}
arOverlayView.registerReceiver();
}
public static Drawable drawableFromUrl(String url) throws IOException {
Bitmap x;
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
connection.connect();
InputStream input = connection.getInputStream();
x = BitmapFactory.decodeStream(input);
return new BitmapDrawable(x);
}
private void initLoadingDialog() {
dialog = new Dialog(this);
dialog.setCancelable(false);
dialog.setContentView(R.layout.show_loading);
TextView txtFind = dialog.findViewById(R.id.findingBeacons);
txtFind.setVisibility(View.VISIBLE);
dialog.setOnKeyListener(new Dialog.OnKeyListener() {
#Override
public boolean onKey(DialogInterface arg0, int keyCode,
KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
dialog.dismiss();
}
return true;
}
});
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));
}
public void showLoading() {
try {
if (dialog != null) {
dialog.show();
} else {
initLoadingDialog();
dialog.show();
}
} catch (Exception e) {
}
}
public void dismissLoading() {
try {
if (dialog != null && dialog.isShowing()) {
dialog.dismiss();
}
} catch (Exception e) {
}
}
}
green screen
Getting like this for camera activity in redmi y2 phone only. Its works well on other models. What might be issue? It shows directions in camera to shop using beacon device. Android os version is not problem.
white screen on some devices - samsung tab, oneplus 7, BLU G9 Pro phone
white screen
this activity shows navigation with help of beacons in camera shows overlay of imageview. it works on some devices, i have tried various methods to resolve it,
doesn't work. added latest camera v2 api.
How can i resolve this issue? thanks in advance.
Sometimes this "green screen" issue is caused by the camera's preview resolution. Try to get supported preview size from camera instance.
mParams = mCamera.getParameters();
List<Camera.Size> supportedPreviewSizes = mParams.getSupportedPreviewSizes();
Camera.Size bestPreviewSize = supportedPreviewSizes.get(0);
for (Camera.Size sz : supportedPreviewSizes) {
/* perfect match */
if(sz.width == mWidth && sz.height == mHeight) {
bestPreviewSize = sz;
break;
} else {
int bestArea = bestPreviewSize.width*bestPreviewSize.height;
int currArea = sz.width*sz.height;
int targetArea = mWidth*mHeight;
if (Math.abs(currArea-targetArea) < Math.abs(bestArea-targetArea)) {
bestPreviewSize = sz;
}
}
}
mCurrWidth = bestPreviewSize.width;
mCurrHeight = bestPreviewSize.height;
mParams.setPreviewSize(mCurrWidth, mCurrHeight);
/* Set preview format */
mParams.setPreviewFormat(ImageFormat.NV21);
/* Apply Parameters */
mCamera.setParameters(mParams);
mCamera.startPreview();
You can also try to force some fixed resolution depending on some device conditions, like display width, for example. Some resolutions i found useful on my use case:
width = 1280;
heigth = 720;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
WindowMetrics windowMetrics = getWindowManager().getCurrentWindowMetrics();
if (isPortrait) {
if (windowMetrics.getBounds().width() <= 720) {
width = 720;
heigth = 480;
}
} else {
if (windowMetrics.getBounds().width() <= 1344) {
width = 960;
heigth = 540;
}
}
} else {
if (isPortrait) {
if (getDisplay().getWidth() <= 720) {
width = 720;
heigth = 480;
}
} else {
if (getDisplay().getWidth() <= 1344) {
width = 960;
heigth = 540;
}
}
}
Keep in mind that the best solution for me was getting the supported sizes to calculate the best preview size.
I don't know what to do now, I'm new to Android.
package com.example.macbookpro.myplayer;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.TextView;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
public class AudioPlayer extends AppCompatActivity implements SeekBar.OnSeekBarChangeListener, MediaPlayer.OnCompletionListener {
ImageView btn_play;
Button btn_pause;
ImageView btn_next;
ImageView btn_prev;
ImageView btn_forward;
ImageView btn_backward;
TextView song_title;
int currentsongindex;
int seekForwardTime = 5000;
int seekBackwardTime = 5000;
private Utilities utilities;
Handler mHandler1=new Handler();
SeekBar song_progressbar;
final ArrayList<File> arrayList = new ArrayList<File>();
MediaPlayer mp = new MediaPlayer();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_audio_player);
btn_play = (ImageView) findViewById(R.id.btn_play);
btn_next = (ImageView) findViewById(R.id.btn_next);
btn_prev = (ImageView) findViewById(R.id.btn_prev);
btn_forward = (ImageView) findViewById(R.id.btn_forward);
btn_backward = (ImageView) findViewById(R.id.btn_backwrd);
song_title = (TextView) findViewById(R.id.tw);
song_progressbar=(SeekBar)findViewById(R.id.song_progressbar);
song_progressbar.setOnSeekBarChangeListener(this);
mp.setOnCompletionListener(this);
try {
PlaySongtwo(getIntent().getStringExtra("index"));
} catch (IOException e) {
e.printStackTrace();
}
final String[] sec = getIntent().getStringArrayExtra("index2");
currentsongindex = Integer.parseInt((getIntent().getStringExtra("positionofcurrentsong")));
utilities = new Utilities();
// Button for playing the song
btn_play.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
if (mp.isPlaying()) {
if (mp != null) {
mp.pause();
btn_play.setImageResource(R.drawable.button_play);
} else {
if (mp != null) {
mp.start();
btn_play.setImageResource(R.drawable.button_pause);
}
}
} else {
if (mp != null) {
mp.start();
btn_play.setImageResource(R.drawable.button_pause);
}
}
}
});
// Button for the next song in the list
btn_next.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
Log.e("currenttt song is ",currentsongindex+"");
if(currentsongindex < (sec.length-1)){
int cc=currentsongindex+1;
Log.e("value in cc",cc+"");
try {
PlaySongtwo(sec[cc]);
} catch (IOException e) {
e.printStackTrace();
}
Log.e("next song number is ",cc +"");
currentsongindex = currentsongindex +1;
}else {
try {
PlaySongtwo(sec[0]);
} catch (IOException e) {
e.printStackTrace();
}
currentsongindex = 0;
}
}
});
//Button for the previous song in the list
btn_prev.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
if(currentsongindex > 0){
int prevsong= currentsongindex-1;
try {
PlaySongtwo(sec[prevsong]);
} catch (IOException e) {
e.printStackTrace();
}
Log.e("prev song",prevsong+"");
currentsongindex = prevsong;
}else {
try {
PlaySongtwo(String.valueOf((sec.length-1)));
} catch (IOException e) {
e.printStackTrace();
}
currentsongindex = sec.length-1;
}
}
});
//Button for fast-forwarding the song
btn_forward.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
int currentPosition = mp.getCurrentPosition();
if(currentPosition + seekForwardTime <= mp.getDuration() ){
mp.seekTo(currentPosition + seekForwardTime);
}else {
mp.seekTo(mp.getDuration());
}
}
});
//Button for fast-backwarding the song
btn_backward.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
int currentPostion = mp.getCurrentPosition();
if(currentPostion - seekBackwardTime >= 0){
mp.seekTo(currentPostion - seekBackwardTime);
}else {
mp.seekTo(0);
}
}
});
}
private void PlaySongtwo(String path) throws IOException {
try {
String songname = path.substring(path.lastIndexOf("/") + 1);
song_title.setText(songname);
mp.reset();
Uri myUri = Uri.parse(path);
mp.setDataSource(AudioPlayer.this, myUri);
mp.prepare();
mp.start();
btn_play.setImageResource(R.drawable.button_pause);
song_progressbar.setProgress(0);
song_progressbar.setMax(100);
updateProgressBar1();
} catch (IOException e) {
e.printStackTrace();
}
}
private void updateProgressBar1() {
mHandler1.postDelayed(mUpdateTimeTask1,100);
}
private Runnable mUpdateTimeTask1=new Runnable() {
#Override
public void run() {
long totalDuration = mp.getDuration();
long currentDuration=mp.getCurrentPosition();
int progress=(int)(utilities.getProgresspercentage(currentDuration,totalDuration));
song_progressbar.setProgress(progress);
mHandler1.postDelayed(this,100);
}
};
#Override
protected void onDestroy ()
{
super.onDestroy();
mp.release();
}
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) {
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
mHandler1.removeCallbacks(mUpdateTimeTask1);
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
mHandler1.removeCallbacks(mUpdateTimeTask1);
int totalDuration=mp.getDuration();
int currentPosition=utilities.progressToTimer(seekBar.getProgress(),totalDuration);
mp.seekTo(currentPosition);
updateProgressBar1();
}
#Override
public void onCompletion(MediaPlayer mp1) {
enter code here
}
}
This is the error I'm facing.
11-06 13:30:03.935 1060-1060/com.example.macbookpro.myplayer E/MediaPlayer: Should have subtitle controller already set
11-06 13:30:04.031 1060-1060/com.example.macbookpro.myplayer E/MediaPlayer: Should have subtitle controller already set
11-06 13:30:22.260 1060-1060/com.example.macbookpro.myplayer D/AndroidRuntime: Shutting down VM
11-06 13:30:22.261 1060-1060/com.example.macbookpro.myplayer E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.macbookpro.myplayer, PID: 1060
java.lang.IllegalStateException
at android.media.MediaPlayer.getDuration(Native Method)
at com.example.macbookpro.myplayer.AudioPlayer$6.run(AudioPlayer.java:220)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
My guess is that you are trying to getDuration before your MediaPlayer is ready to be used.
Make sure you're setting all controls that interact with the mediaplayer.
This is my code I have got repeat one working but I want to be able to repeat all songs so it does not stop playing the music, I also want to be able to repeat one single song. I have tried to find documentation to help me but I haven't found anything. Any help would be appreciated
import android.Manifest;
import android.app.Activity;
import android.content.pm.PackageManager;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ImageButton;
import android.widget.SeekBar;
import android.widget.TextView;
import java.io.IOException;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.TimeUnit;
import static android.R.drawable.ic_media_play;
public class MainActivity extends Activity {
private static final int UPDATE_FREQUENCY = 500;
private static final int STEP_VALUE = 5000;
private static final int CALL = 872;
static MediaPlayer mp = null;
private final Handler handler = new Handler();
private TextView selectedFile;
private TextView selectedArtist;
private RecyclerView recyclerView;
private SeekBar seekbar;
private MediaPlayer player;
private ImageButton playButton;
private ImageButton prevButton;
private ImageButton nextButton;
private ImageButton repeatButton;
private ImageButton shuffleButton;
private boolean isStarted = true;
private int currentPosition;
private boolean isMovingSeekBar = false;
private MyRecyclerViewAdapter adapter;
private final Runnable updatePositionRunnable = new Runnable() {
public void run() {
updatePosition();
}
};
private List<Music> musicList;
private boolean isShuffle = false;
private boolean isRepeat = false;
private View.OnClickListener onButtonClick = new View.OnClickListener() {
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.play:
if (player.isPlaying()) {
handler.removeCallbacks(updatePositionRunnable);
player.pause();
playButton.setImageResource(android.R.drawable.ic_media_play);
} else {
if (isStarted) {
player.start();
playButton.setImageResource(android.R.drawable.ic_media_pause);
updatePosition();
} else {
startPlay(currentPosition);
}
}
break;
case R.id.prev:
startPlay(currentPosition - 1);
break;
case R.id.next:
startPlay(currentPosition + 1);
break;
case R.id.shuffle:
if (isShuffle) {
Collections.shuffle(musicList);
adapter.notifyDataSetChanged();
shuffleButton.setColorFilter(-16776961);
} else {
sortMusicList();
shuffleButton.setColorFilter(-16777216);
}
isShuffle = !isShuffle;
break;
case R.id.repeat: {
if (isRepeat) {
player.setLooping(true);
repeatButton.setImageResource(R.drawable.ic_repeat_black_24dp);
repeatButton.setColorFilter(-16776961);
} else {
player.setLooping(false);
repeatButton.setColorFilter(-16777216);
}
break;
}
}
}
};
private void sortMusicList() {
Collections.sort(musicList, new Comparator<Music>() {
#Override
public int compare(Music o1, Music o2) {
return o1.getArtists().compareTo(o2.getArtists());
}
});
if (adapter != null) {
adapter.notifyDataSetChanged();
}
}
private MediaPlayer.OnCompletionListener onCompletion = new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
stopPlay();
startPlay(currentPosition + 1);
}
};
private MediaPlayer.OnErrorListener onError = new MediaPlayer.OnErrorListener() {
#Override
public boolean onError(MediaPlayer mp, int what, int extra) {
return false;
}
};
private SeekBar.OnSeekBarChangeListener seekBarChanged = new SeekBar.OnSeekBarChangeListener() {
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
isMovingSeekBar = false;
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
isMovingSeekBar = true;
}
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (isMovingSeekBar) {
player.seekTo(progress);
Log.i("OnSeekBarChangeListener", "onProgressChanged");
} else {
TextView duration = findViewById(R.id.song_duration);
duration.setText(String.valueOf(progress));
long totalSeconds = TimeUnit.MILLISECONDS.toSeconds(progress);
long minss = totalSeconds / 60;
long seconds = totalSeconds % 60;
duration.setText(String.format(Locale.UK, "%02d:%02d", minss, seconds));
}
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main3);
recyclerView = findViewById(R.id.list);
recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
int permissionCheck = ContextCompat.checkSelfPermission(this,
Manifest.permission.READ_EXTERNAL_STORAGE);
if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
setupUI();
} else {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
CALL);
}
}
#Override
protected void onPause() {
super.onPause();
player.getCurrentPosition();
}
private void setupUI() {
selectedFile = findViewById(R.id.selected_file);
selectedArtist = findViewById(R.id.artists);
seekbar = findViewById(R.id.seekbar);
prevButton = findViewById(R.id.prev);
playButton = findViewById(R.id.play);
nextButton = findViewById(R.id.next);
repeatButton = findViewById(R.id.repeat);
shuffleButton = findViewById(R.id.shuffle);
player = new MediaPlayer();
player.setOnCompletionListener(onCompletion);
player.setOnErrorListener(onError);
seekbar.setOnSeekBarChangeListener(seekBarChanged);
musicList = new MusicManager().getMusic(getContentResolver());
sortMusicList();
adapter = new MyRecyclerViewAdapter(musicList);
adapter.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
startPlay(position);
}
});
recyclerView.setAdapter(adapter);
prevButton.setOnClickListener(onButtonClick);
playButton.setOnClickListener(onButtonClick);
nextButton.setOnClickListener(onButtonClick);
shuffleButton.setOnClickListener(onButtonClick);
repeatButton.setOnClickListener(onButtonClick);
}
#Override
protected void onDestroy() {
super.onDestroy();
handler.removeCallbacks(updatePositionRunnable);
player.stop();
player.reset();
player.release();
player = null;
}
private void startPlay(int position) {
if (position < 0) {
position = 0;
}
if (position >= musicList.size()) {
position = musicList.size() - 1;
}
String file = musicList.get(position).getFile();
String title = musicList.get(position).getTitle();
String artists = musicList.get(position).getArtists();
currentPosition = position;
if (artists != null) {
selectedArtist.setText(artists);
}
if (title != null) {
selectedFile.setText(title);
}
seekbar.setProgress(0);
updatePosition();
player.stop();
player.reset();
try {
player.setDataSource(file);
player.prepare();
player.start();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
seekbar.setMax(player.getDuration());
playButton.setImageResource(android.R.drawable.ic_media_pause);
isStarted = true;
}
private void stopPlay() {
player.stop();
player.reset();
playButton.setImageResource(ic_media_play);
handler.removeCallbacks(updatePositionRunnable);
isStarted = false;
}
private void updatePosition() {
handler.removeCallbacks(updatePositionRunnable);
seekbar.setProgress(player.getCurrentPosition());
handler.postDelayed(updatePositionRunnable, UPDATE_FREQUENCY);
if (adapter == null) {
return;
}
}
}
this is just the main activity if you need anything else just ask.
To play a list of songs loop continuously, you can define a variable to be used as an index of the number of songs completed. After completion of the of the list, replay the list of songs by calling the index again. An example of this is:
int[] myAudio = {R.raw.audio1, R.raw.audio2, R.raw.audio3};
int mSongFinish = 0;
MediaPlayer mp = MediaPlayer.create(this, myAudio[0]);
mp.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
mSongFinish++;
mp.reset();
if (mSongFinish < myAudio.length()) {
try {
AssetFileDescriptor asset = getResources().openRawResourceFd(myAudio[mSongFinish]);
if (asset != null) {
mp.setDataSource(afd.getFileDescriptor(), asset.getStartOffset(), asset.getLength());
asset.close();
mp.prepare();
}
} catch (Exception ex) {
// report a crash
}
} else {
mSongFinish=0;
mp.release();
mp = null; // either set counter to 0 and start again or call end of list
}
}
});
mp.start();
To do this on a button click, just use an onClickListener. To loop a single song on button click, use mp.setLooping(true).
while playing music using this mediaplayer, whenever a call comes, home button is pressed and lockscreen appears and on return to the app after the above problems...the play button in the app doesnt respond....I want to pause the music untill I return to the app and should continue playing from where it had stopped......plz help...
ekdanta.java
public class ekdanta extends AppCompatActivity implements Runnable,View.OnClickListener,SeekBar.OnSeekBarChangeListener {
TextView tv4;
Button b9, b10,but19;
int count = 0;
MediaPlayer play;
SeekBar seek_bar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ekdanta);
tv4 = (TextView) findViewById(R.id.textView9);
tv4.setTextSize((float)21.5);
tv4.setText(Html.fromHtml(getString(R.string.thirteen)));
b9 = (Button) findViewById(R.id.b9);
b10 = (Button) findViewById(R.id.b10);
seek_bar = (SeekBar) findViewById(R.id.seekBar);
seek_bar.setOnSeekBarChangeListener(this);
seek_bar.setEnabled(false);
but19 = (Button) findViewById(R.id.button19);
but19.setOnClickListener(this);
}
public void run() {
int currentPosition= play.getCurrentPosition();
int total = play.getDuration();
while (play!=null && currentPosition<total) {
try {
Thread.sleep(1000);
currentPosition= play.getCurrentPosition();
} catch (InterruptedException e) {
return;
} catch (Exception e) {
return;
}
seek_bar.setProgress(currentPosition);
}
}
public void onClick(View v) {
if (v.equals(but19)) {
if (play == null) {
play = MediaPlayer.create(getApplicationContext(), R.raw.ekadanta);
seek_bar.setEnabled(true);
}
if (play.isPlaying()) {
play.pause();
but19.setText("Play");
} else {
play.start();
but19.setText("Pause");
seek_bar.setMax(play.getDuration());
new Thread(this).start();
}
}
}
#Override
protected void onPause() {
if(play!=null){
play.stop();
}
super.onPause();
}
public void increase(View inc) {
count++;
if (count == 1) {
tv4.setTextSize(25);
} else if (count == 2) {
tv4.setTextSize(30);
} else if (count >= 3) {
count = 3;
tv4.setTextSize(40);
}
}
public void decrease(View dec) {
count--;
if (count <= 0) {
tv4.setTextSize((float)21.5);
count = 0;
}
if (count == 1) {
tv4.setTextSize(25);
} else if (count == 2) {
tv4.setTextSize(30);
} else if (count == 3) {
tv4.setTextSize(40);
}
}
#Override
public void onProgressChanged(SeekBar seek_bar, int progress, boolean fromUser) {
try{
if(play.isPlaying()||play!=null){
if (fromUser)
play.seekTo(progress);
}
else if(play==null){
Toast.makeText(getApplicationContext(),"First Play",Toast.LENGTH_SHORT).show();
seek_bar.setProgress(0);
}
}
catch(Exception e){
Log.e("seek bar",""+e);
seek_bar.setEnabled(false);
}
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
}
#Override
protected void onPause()
{
super.onPause();
if (play3!= null)
{
play3.pause();
}
}
#Override
protected void onResume()
{
super.onResume();
if ((play3 != null) && (!play3.isPlaying())) {
but32.setText("Play");
but32.setOnClickListener(this);
}
}
This helped me to overcome my problems.....I'm able to play the music which gets paused when home button/lockscreen/calls appears...from where it had stopped
My application contains one mediaplayer with one (play/pause) button in audio.xml , but the problem is that I am not able to find right code to stop MediaPlayer before the page gets destroyed and because of that the app crashes when i log in audio page (xml) and quit without running mediaplayer , here is the code i used:
public class audio extends Langue implements Runnable,
OnClickListener, OnSeekBarChangeListener {
private SeekBar seekBar;
private Button startMedia;
// private Button stopMedia;
private MediaPlayer mp;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.audio);
seekBar = (SeekBar) findViewById(R.id.seekBar1);
startMedia = (Button) findViewById(R.id.button1);
//stopMedia = (Button) findViewById(R.id.button2);
startMedia.setOnClickListener(this);
//stopMedia.setOnClickListener(this);
seekBar.setOnSeekBarChangeListener(this);
seekBar.setEnabled(false);
}
public void run() {
int currentPosition = mp.getCurrentPosition();
int total = mp.getDuration();
while (mp != null && currentPosition < total) {
try {
Thread.sleep(1000);
currentPosition = mp.getCurrentPosition();
} catch (InterruptedException e) {
return;
} catch (Exception e) {
return;
}
seekBar.setProgress(currentPosition);
}
}
public void onClick(View v) {
if (v.equals(startMedia)) {
if (mp == null) {
mp = MediaPlayer.create(getApplicationContext(), R.raw.espoir);
seekBar.setEnabled(true);
}
if (mp.isPlaying()) {
mp.pause();
startMedia.setText("Play");
} else {
mp.start();
startMedia.setText("Pause");
seekBar.setMax(mp.getDuration());
new Thread(this).start();
}
}
/* if (v.equals(stopMedia) && mp != null) {
if (mp.isPlaying() || mp.getDuration() > 0) {
mp.stop();
mp = null;
startMedia.setText("Play");
seekBar.setProgress(0);
}
}
*/
}
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
try {
if (mp.isPlaying() || mp != null) {
if (fromUser)
mp.seekTo(progress);
} else if (mp == null) {
Toast.makeText(getApplicationContext(), "Media is not running",
Toast.LENGTH_SHORT).show();
seekBar.setProgress(0);
}
} catch (Exception e) {
Log.e("seek bar", "" + e);
seekBar.setEnabled(false);
}
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
this.finish();
return true;
}
return super.onOptionsItemSelected(item);
}
// stop song
#Override
protected void onPause(){
super.onPause();
mp.stop();
finish();
}
}
Do something like this into the onPause() method for preventing crash
try{
mp.stop();
} catch(Exception e) {
}
finish();