The problem with moving to the next track - java

I'm making a music player, and there was a problem when switching to the next song. When the phone is in working condition (the screen is on) the tracks switch smoothly, when the screen is off there is a long pause, the song starts only after a long time (very long!!!) or when the screen is turned on. Also, everything works well with a headset (Bluetooth), songs switch smoothly even when the screen is turned off. I use MediaPlayer.prepare to prepare the track (music files are taken from the SD card, so I don't see any point in using MediaPlayer.prepareAsync()). Songs are played using Service. Since the player works fine when the screen is turned on and poorly when it is turned off, then this is the problem. I tried everything, searched all the articles about media player in Russian and English, reviewed YouTube. Help is also accepted on Kotlin.
(here is the same question. but there is no answer. How to use wake lock for android mediaplayer?)
Below is the code:
public class MusicService extends Service implements MediaPlayer.OnCompletionListener,
MediaPlayer.OnPreparedListener {
IBinder mBinder = new MyBinder();
private MediaPlayer mediaPlayer = null;
private Uri uri;
private int position = POSITION_PLAY;
public static AudioManager audioManager;
int result;
private NotificationReceiver notificationReceiver;
#Override
public void onCreate() {
super.onCreate();
notificationReceiver = new NotificationReceiver();
audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
result = audioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC,
AudioManager.AUDIOFOCUS_GAIN);
if (result != AudioManager.AUDIOFOCUS_REQUEST_GRANTED)
return;
IntentFilter intentFilter = new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
registerReceiver(notificationReceiver, intentFilter);
}
#Override
public void onDestroy() {
super.onDestroy();
releaseMP();
unregisterReceiver(notificationReceiver);
audioManager.abandonAudioFocus(this);
Log.e(TAG, "onDestroy()");
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
public class MyBinder extends Binder {
MusicService getService() {
return MusicService.this;
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(myPosition != -1){
playMedia(myPosition);
}
return START_STICKY;
}
public void createMediaPlayer(int positionInner) {
position = positionInner;
uri = Uri.parse(musicFiles.get(position).getPath());
mediaPlayer = null;
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
mediaPlayer.setDataSource(getApplicationContext(), uri);
} catch (IOException ioException) {
ioException.printStackTrace();
}
prepare();
}
private void playMedia(int position) {
if(mediaPlayer != null) {
mediaPlayer.stop();
releaseMP();
}
createMediaPlayer(position);
mediaPlayer.start();
}
public void prepare() {
try {
mediaPlayer.prepare();
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
void showNotification(int playPauseBtn){
...
startForeground(2, notification);
if(!isGoing && IS_LIVE) {
stopForeground(false);
}
}
void OnCompleted(){
mediaPlayer.setOnCompletionListener(this);
}
void OnPrepared() { mediaPlayer.setOnPreparedListener(this);}
#Override
public void onCompletion(MediaPlayer mp) {
if(actionPlaying != null){
actionPlaying.nextBtnClicked();
if(mediaPlayer != null){
mediaPlayer.start();
OnCompleted();
}
}
}
private void releaseMP() {
if (mediaPlayer != null) {
try {
mediaPlayer.release();
mediaPlayer = null;
} catch (Exception e) {
e.printStackTrace();
}
}
}
#Override
public void onPrepared(MediaPlayer mp) {
mp.start();
}
public void start() {
mediaPlayer.start();
}
public boolean isPlaying() {
return mediaPlayer.isPlaying();
}
public void stop() {
mediaPlayer.stop();
}
public void pause() {
mediaPlayer.pause();
}
public void release() {
releaseMP();
}
public int getDuration() {
return mediaPlayer.getDuration();
}
public void seekTo(int position) {
mediaPlayer.seekTo(position);
}
public int getCurrentPosition() {
return mediaPlayer.getCurrentPosition();
}
}
Code for the method:
public void nextBtnClicked() {
if(musicService.isPlaying()) {
musicService.stop();
musicService.release();
if(SHUFFLE && !REPEAT){
POSITION_PLAY = getRandom(ListSongs.size() - 1);
}
else if(!SHUFFLE && !REPEAT){
POSITION_PLAY = ((POSITION_PLAY + 1) % ListSongs.size());
}
uri = Uri.parse(ListSongs.get(POSITION_PLAY).getPath());
musicService.createMediaPlayer(POSITION_PLAY);
if(is_live_player_activity) {
metaData(uri);
}
musicService.OnCompleted();
musicService.showNotification(R.drawable.ic_pause);
playPauseBtn.setBackgroundResource(R.drawable.ic_pause);
musicService.start();
}
else {
musicService.stop();
musicService.release();
if(SHUFFLE && !REPEAT){
POSITION_PLAY = getRandom(ListSongs.size() - 1);
}
else if(!SHUFFLE && !REPEAT){
POSITION_PLAY = ((POSITION_PLAY + 1) % ListSongs.size());
}
uri = Uri.parse(ListSongs.get(POSITION_PLAY).getPath());
musicService.createMediaPlayer(POSITION_PLAY);
if(is_live_player_activity) {
metaData(uri);
}
musicService.OnCompleted();
if(FLAG){
musicService.showNotification(R.drawable.ic_pause);
playPauseBtn.setBackgroundResource(R.drawable.ic_pause);
} else {
musicService.showNotification(R.drawable.ic_play);
playPauseBtn.setBackgroundResource(R.drawable.ic_play);
}
}
}
Manifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.music">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:name=".ApplicationClass"
android:screenOrientation="portrait"
android:theme="#style/Theme.Music">
<activity android:name=".MusicActivity"
android:screenOrientation="portrait"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
...
<service android:name=".MusicService" android:enabled="true"/>
<receiver android:name=".NotificationReceiver" android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
<action android:name="android.media.AUDIO_BECOMING_NOISY" />
<action android:name="actionprevious" />
<action android:name="actionnext" />
<action android:name="actionplay" />
</intent-filter>
</receiver>
</application>
</manifest>

I found a problem. It was necessary to call MediaPlayer.setwakemode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);

Related

Android SMS receiver call twice

I would like to notify the incoming sms message. I implemented the BroadcastReceiver for SMS receiver. And I also implemented the service for BOOT_COMPLETED action. Because the receiver cannot be registered if the device is reboot. When I launch the apps, that only call onReceiver once. But I reboot the device and start the BOOT_COMPLETED service. That will make the onReceive method call twice. But I don't know why. I confirm I only register the receiver once.
ps: When I reboot the device, I received the log order is enable receiver, register receiver, enable receive, onReceived, onReceived
Here is my code:
AutoStartService.java
public class AutoStartService extends Service {
private SmsReceiver smsReceiver;
public static boolean isStarted = false;
#Override
public void onCreate() {
super.onCreate();
isStarted = true;
if(!SmsReceiver.isEnableReceiver && smsReceiver == null) {
smsReceiver = new SmsReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("android.provider.Telephony.SMS_RECEIVED");
registerReceiver(smsReceiver, intentFilter);
Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
Log.e("AAA", "register receiver");
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return Service.START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
isStarted = false;
Toast.makeText(this, "Service Destroy", Toast.LENGTH_LONG).show();
}
#Override
public IBinder onBind(Intent arg0) {
return null;
}
BootCompleteReceiver.java
public class BootCompleteReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if(!AutoStartService.isStarted) {
new Handler().postDelayed(() -> {
Intent service = new Intent(context, AutoStartService.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(service);
} else {
context.startService(service);
}
}, 500);
}
}
}
SmsReceiver.java
public class SmsReceiver extends BroadcastReceiver implements SmsHelper.SmsHelperDelegate {
private static final String SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";
public static boolean isEnableReceiver = false;
public SmsReceiver() {
super();
isEnableReceiver = true;
Log.e("AAA", "enable receiver");
}
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(SMS_RECEIVED)) {
Bundle bundle = intent.getExtras();
if (bundle != null) {
Log.e("SmsReceiver", "onReceived");
}
}
}
AndroidManifest.xml
<receiver android:name=".receiver.SmsReceiver" android:enabled="true" android:exported="true">
<intent-filter android:priority="2147483647">
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
<service android:name=".receiver.AutoStartService" android:exported="true"/>
<receiver android:name=".receiver.BootCompleteReceiver" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>

Difficulty identifying outgoing and incoming calls (when app is open or closed)

When there are outgoing and incoming calls, toast should appear on the screen but it does not appear. Is the code incorrect?
Manifast premissions:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_CALL_LOG" />
Manifast (receiver):
<receiver android:name=".model.CallReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
</intent-filter>
</receiver>
MainActivity
if (ContextCompat.checkSelfPermission( this, READ_PHONE_STATE)!=PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions( this, new String[]{READ_PHONE_STATE} , 369);
}
class:
public class CallReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context , Intent intent) {
if (intent.getStringExtra( TelephonyManager.EXTRA_STATE )==TelephonyManager.EXTRA_STATE_OFFHOOK){
showToastMsg(context,"phone call is Started...");
}else { if (intent.getStringExtra( TelephonyManager.EXTRA_STATE )==TelephonyManager.EXTRA_STATE_IDLE){
showToastMsg(context,"phone call is Ended...");
}else { if (intent.getStringExtra( TelephonyManager.EXTRA_STATE )==TelephonyManager.EXTRA_STATE_RINGING){
showToastMsg(context,"Incoming Call...");
}
}
}
}
private void showToastMsg(Context c,String msg) {
Toast.makeText( c, msg, Toast.LENGTH_LONG).show();
}
}
You need the service to handle incoming or outgoing calls when the app is closed.
Manifest.xml
<receiver android:name=".services.CallRecevier">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
<service
android:name=".services.CallService"
android:exported="false" />
CallReceiver
public class CallRecevier extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
try {
Intent svc = new Intent(context, CallService.class);
TelephonyManager telephony = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
telephony.listen(new PhoneStateListener() {
#Override
public void onCallStateChanged(int state, String phoneNumber) {
super.onCallStateChanged(state, phoneNumber);
if (state == 1 || state == 2) {
if (phoneNumber != null && !phoneNumber.equals("")) {
svc.putExtra("num", phoneNumber);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(svc);
} else {
context.startService(svc);
}
}
} else if (state == 0) {
context.stopService(svc);
}
}
}, PhoneStateListener.LISTEN_CALL_STATE);
} catch (Exception e) {
Timber.e("Error: %s", e.getLocalizedMessage());
}
}
}
CallService
public class CallService extends Service {
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
}
}
#Override
public ComponentName startForegroundService(Intent service) {
if (service.getStringExtra("num") != null) {
String number = service.getStringExtra("num");
Toast.makeText(getApplicationContext(),number,Toast.LENGTH_SHORT).show();
}
return super.startForegroundService(service);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null && intent.getStringExtra("num") != null) {
String number = intent.getStringExtra("num");
Toast.makeText(getApplicationContext(),number,Toast.LENGTH_SHORT).show();
}
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy() {
super.onDestroy();
}
}
Use this code it is working on android 11 and 9
in manifest
<receiver android:name=".Receivers.CallReceiver">
<intent-filter android:priority="999">
<action android:name="android.intent.action.PHONE_STATE" />
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
</intent-filter>
</receiver>
Call Receiver
public class CallReceiver extends BroadcastReceiver {
private static boolean ring = false, callReceived = false, isIncoming = false;
private static int lastState = TelephonyManager.CALL_STATE_IDLE;
String phoneNumber, extraState;
int currentState = 0;
MediaRecorder recorder;
SharedPref sh;
CallLogs callLogs;
String phNumber, dir;
#SuppressLint("UnsafeProtectedBroadcastReceiver")
#Override
public void onReceive(Context context, Intent intent) {
sh = new SharedPref(context);
audioFileRef = FirebaseStorage.getInstance().getReference().child("Audio Files");
phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
extraState = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
startCallService(context, intent);
}
private void startCallService(Context context, Intent intent) {
if (extraState != null) {
if (extraState.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) {
currentState = TelephonyManager.CALL_STATE_OFFHOOK;
phoneNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
if (phoneNumber != null) {
Toast.makeText(context, "Off hock" + phoneNumber, Toast.LENGTH_SHORT).show();
if (ring) {
callReceived = true;
}
if (lastState != TelephonyManager.CALL_STATE_RINGING) {
isIncoming = false;
Toast.makeText(context, "onOutgoingCallStarted", Toast.LENGTH_SHORT).show();
} else {
isIncoming = true;
Toast.makeText(context, "onIncomingCallAnswered", Toast.LENGTH_SHORT).show();
}
startRecording(context);
}
} else if (extraState.equals(TelephonyManager.EXTRA_STATE_IDLE)) {
phoneNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
if (phoneNumber != null) {
// Toast.makeText(context, "Idle" + phoneNumber, Toast.LENGTH_SHORT).show();
if (ring && !callReceived) {
ring = false;
}
callReceived = false;
if (lastState == TelephonyManager.CALL_STATE_RINGING) {
//Ring but no pickup- a miss
uploadCallLog(context);
Toast.makeText(context, "onMissedCall", Toast.LENGTH_SHORT).show();
} else if (isIncoming) {
Toast.makeText(context, "onIncomingCallEnded", Toast.LENGTH_SHORT).show();
uploadCallLog(context);
if (recorder != null) {
recorder.stop();
}
} else {
Toast.makeText(context, "onOutgoingCallEnded", Toast.LENGTH_SHORT).show();
uploadCallLog(context);
if (recorder != null) {
recorder.stop();
}
}
}
currentState = TelephonyManager.CALL_STATE_IDLE;
} else if (extraState.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
currentState = TelephonyManager.CALL_STATE_RINGING;
if (phoneNumber == null)
phoneNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
if (phoneNumber != null) {
ring = true;
isIncoming = true;
Toast.makeText(context, "Ring" + phoneNumber, Toast.LENGTH_SHORT).show();
context.startService(new Intent(context, UploadNewCallLog.class));
}
}
lastState = currentState;
} else if (phoneNumber != null) {
//setIntent(context, Constants.TYPE_CALL_OUTGOING);
Toast.makeText(context, "Outgoing" + phoneNumber, Toast.LENGTH_SHORT).show();
}
}
}

How to update a service running in a separate process when the Android app is updated?

When I update the app to a new version, the service that was installed with the previous app version is still running. When I update the app the second time, the updated service is running properly.
However, after first update, whenever i close the app or restart the phone the service from the previous version is running.
How can i force the new service to run as soon as the app is updated.
Here is my code
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.djuro.updateservicewithappupdate">
<application
android:name=".App"
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".MyService"
android:process=":myService" />
<receiver android:name=".PackageReplacedReceiver">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_REMOVED" />
<data android:scheme="package" android:path="com.djuro.updateservicewithappupdate"/>
</intent-filter>
</receiver>
</application>
</manifest>
App.java
public class App extends Application {
private static final String TAG = App.class.getName();
private static App mInstance;
private Messenger myServiceMessenger;
private boolean isBound;
private Messenger replyMessenger = new Messenger(new IncomingHandler());
#Override
public void onCreate() {
super.onCreate();
if (mInstance == null) {
mInstance = this;
startMyService();
}
isBound = false;
// start the chore service (if it is not running) and bind to it
}
public void startMyService() {
startService(new Intent(mInstance, MyService.class));
doBindService();
}
public void stopMyService() {
doUnBindService(true);
stopService(new Intent(mInstance, MyService.class));
}
public static App getInstance() {
return mInstance;
}
public static Context getContext() {
return mInstance.getApplicationContext();
}
public static Messenger getChoreMessenger() {return mInstance.myServiceMessenger;}
#Override
public void onTerminate() {
doUnBindService(false);
super.onTerminate();
}
private void doBindService() {
if (!isBound) {
Log.d(TAG, "Binding ChoreService.");
bindService(new Intent(this, MyService.class), myServiceConnection, Context.BIND_AUTO_CREATE);
isBound = true;
}
}
private void doUnBindService(boolean restartService) {
if (isBound) {
Log.d(TAG, "Unbinding ChoreService.");
if (myServiceMessenger != null) {
try {
Message msg = Message.obtain(null, MyService.UNREGISTER_CLIENT);
msg.replyTo = replyMessenger;
replyMessenger.send(msg);
}
catch (RemoteException e) {
// There is nothing special we need to do if the service has crashed.
}
}
if (restartService) {
try {
Message msg = Message.obtain(null, MyService.STOP_SERVICE_ON_UNBIND);
msg.replyTo = replyMessenger;
replyMessenger.send(msg);
}
catch (RemoteException e) {
// There is nothing special we need to do if the service has crashed.
}
}
unbindService(myServiceConnection);
isBound = false;
} else if (restartService) {
stopService(new Intent(mInstance, MyService.class));
}
}
private ServiceConnection myServiceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
myServiceMessenger = new Messenger(service);
Log.d(TAG, "connected to service");
try {
Message msg = Message.obtain(null, MyService.REGISTER_CLIENT);
msg.replyTo = replyMessenger;
myServiceMessenger.send(msg);
}
catch (RemoteException e) {
// In this case the service has crashed before we could even do anything with it
}
}
public void onServiceDisconnected(ComponentName className) {
myServiceMessenger = null;
Log.d(TAG, "disconnected from ChoreService");
}
};
class IncomingHandler extends Handler {
#Override
public void handleMessage(Message msg) {
}
}
}
MyService.java
public class MyService extends Service {
private static final String TAG = MyService.class.getName();
public static final int UNREGISTER_CLIENT = 1;
public static final int REGISTER_CLIENT = 2;
public static final int STOP_SERVICE_ON_UNBIND = 3;
final Messenger messenger = new Messenger(new IncomingHandler());
private String appVersion;
private boolean stopOnUnbind;
private int boundCount = 0;
// called when the intent starts the Service
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
//return super.onStartCommand(intent, flags, startId);
Log.d(TAG, "onStartCommand()");
getVersion();
return START_STICKY;
}
// called once at creation (before onStartCommand)
#Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate");
}
// used to bind intent to service
#Nullable
#Override
public IBinder onBind(Intent intent) {
//doStopForeground();
boundCount ++;
Log.d(TAG, "bound count: " + boundCount);
return messenger.getBinder();
}
#Override
public boolean onUnbind(Intent intent) {
boundCount --;
Log.d(TAG, "bound count: " + boundCount);
boolean result = super.onUnbind(intent);
if (stopOnUnbind) {
Log.d(TAG, "stopSelf()");
stopSelf();
}
return result;
}
// called when the service is destroyed
#Override
public void onDestroy() {
Log.d(TAG, "onDestroy()");
super.onDestroy();
}
public void getVersion() {
try {
PackageInfo pInfo = this.getPackageManager().getPackageInfo(getPackageName(), 0);
appVersion = pInfo.versionName;
Log.d(TAG, "appVersion: " + appVersion);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
}
private class IncomingHandler extends Handler {
#Override
public void handleMessage(Message msg) {
Log.d(TAG, "IncomingHandler handling message. msg.what= " + msg.what);
switch (msg.what) {
case STOP_SERVICE_ON_UNBIND:
stopOnUnbind = true;
break;
default:
super.handleMessage(msg);
break;
}
}
}
}
PackageReplacedReceiver.java
public class PackageReplacedReceiver extends BroadcastReceiver {
private static final String TAG = PackageReplacedReceiver.class.getName();
#Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "package updated");
App.getInstance().stopMyService();
}
}
Use android.intent.action.MY_PACKAGE_REPLACED action in your intent filer and stop your service from broadcast receiver.
<receiver android:name=".PackageReplacedReceiver" android:enabled="#bool/is_at_least_api_12" > <intent-filter>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
</intent-filter>
</receiver>

Android Bluetooth Scanner Not Running as a Service

I'm trying to run bluetooth beacon scanner as a service, so when the application is not active, when beacon is detected, a notification can.
The Service Code (Java) :
public class BtService extends Service {
public static final String TAG = BtService.class.getSimpleName();
private ScanCallback mScanCallback;
private BluetoothAdapter btAdapter;
private BluetoothLeScanner btScanner;
private boolean mIsScanning = false;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "OnCreate Service");
final BluetoothManager btManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
btAdapter = btManager.getAdapter();
initBtCallBack();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "OnStartCommand Service");
btStartScanning();
return Service.START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "Destroy");
btStopScanning();
}
/**
* BlueTooth CallBack
*/
private void initBtCallBack() {
Log.d(TAG, "InitBtCallBack");
try {
btScanner = btAdapter.getBluetoothLeScanner();
} catch (Exception e) {
e.printStackTrace();
}
mScanCallback = new ScanCallback() {
#Override
public void onScanResult(int callbackType, ScanResult result) {
Log.i(TAG, "Something found : " + result.getDevice().getAddress());
BluetoothDevice device = result.getDevice();
Log.i(TAG, "btDevice : " + device.toString());
Log.i(TAG, "result : " + result.toString());
btUseBeacon(result);
}
};
}
private void btStartScanning() {
if (btScanner != null) {
if(! mIsScanning) {
Log.i(TAG, "START scanning...");
myBeacons.clear();
loadMyBeaconList();
mIsScanning = true;
btScanner.startScan(mScanCallback);
}
} else {
Log.i(TAG, "CANNOT START Scanning");
}
}
private void btStopScanning() {
if(mIsScanning) {
Log.i(TAG, "STOP scanning");
mIsScanning = false;
btScanner.stopScan(mScanCallback);
saveMyBeaconList();
}
}
}
There also a BroadcastReceiver Class to start the Service
public class BtStartServiceReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent service = new Intent(context, BtService.class);
context.startService(service);
}
}
Déclaration in the Manifest.xml, between the . Permission for Boot_Completed as also been added.
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<service
android:name=".BtService"
android:icon="#mipmap/ic_launcher"
android:enabled="true">
</service>
<receiver android:name=".BtStartServiceReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
When the application is active or not, seems it does not work. In the logcat, I don't see any of the LOG i added in the code of the service.
When I kill the application, the logcat shows that the application is restarting, but nothing about Logs in code.
When I try to run this code adapted for an Activity, It works, beacon are detected and can make notification.
I don't wan't to use any beacon library or SDK, as I work with generic beacon.
Thank's for your help.

How to add Image Slider view on lock screen in android

My Code,
public class SecondTextView extends Service {
private BroadcastReceiver mReceiver;
private boolean isShowing = false;
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
private WindowManager windowManager;
private ImageView floatIcon;
WindowManager.LayoutParams params;
#Override
public void onCreate() {
super.onCreate();
windowManager = (WindowManager)getSystemService(WINDOW_SERVICE);
//add floatIcon and its properties;
/* floatIcon = new TextView(this);
floatIcon.setText("Hello There!");
floatIcon.setTextColor(ContextCompat.getColor(this, android.R.color.white));
floatIcon.setTextSize(32f);*/;
floatIcon = new ImageView(this);
floatIcon.setImageResource(R.drawable.home);
floatIcon.setClickable(true);
//set parameters for the floatIcon;
params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.TOP|Gravity.CENTER_HORIZONTAL;
//Register receiver for determining screen off and if user is present;
mReceiver = new LockScreenStateReceiver();
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_USER_PRESENT);
registerReceiver(mReceiver, filter);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
public class LockScreenStateReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
//if screen is turn off show the floatIcon;
if (!isShowing) {
windowManager.addView(floatIcon, params);
isShowing = true;
}
}
else if(intent.getAction().equals(Intent.ACTION_USER_PRESENT)) {
//Handle resuming events if user is present/screen is unlocked remove the floatIcon immediately;
if (isShowing) {
windowManager.removeViewImmediate(floatIcon);
isShowing = false;
}
}
}
}
#Override
public void onDestroy() {
//unregister receiver when the service is destroy;
if (mReceiver != null) {
unregisterReceiver(mReceiver);
}
//remove view if it is showing and the service is destroy;
if (isShowing) {
windowManager.removeViewImmediate(floatIcon);
isShowing = false;
}
super.onDestroy();
}
}
I Used this code but give error and crash my application with
android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRootImpl$W#bed76c6
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.imageonlockscreen" >
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme" >
<activity android:name=".MainActivity" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".SecondTextView"/>
<service android:name=".FloatIcon"/>
</application>

Categories

Resources