Reputation: 1
I am making an application for android 5.1, the essence of which is to transfer voice packets over the UDP protocol between devices, however, when I block the screen of the device itself, socket.receive(packet); as if it falls asleep and ignores all incoming packets, although the Player and PlayerThread themselves are working successfully.
Player.java
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.MulticastSocket;
import java.net.SocketException;
import java.util.concurrent.atomic.AtomicInteger;
import ro.ui.pttdroid.codecs.Speex;
import ro.ui.pttdroid.managers.WakeLockManager;
import ro.ui.pttdroid.managers.WifiLockManager;
import ro.ui.pttdroid.settings.AudioSettings;
import ro.ui.pttdroid.settings.CommSettings;
import ro.ui.pttdroid.util.Audio;
import ro.ui.pttdroid.util.IP;
import ro.ui.pttdroid.util.Log;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.net.wifi.WifiManager;
import android.os.Binder;
import android.os.IBinder;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
public class Player extends Service
{
private WifiManager.WifiLock wifiLock;
private PlayerThread playerThread;
private IBinder playerBinder = new PlayerBinder();
private TelephonyManager telephonyManager;
private PhoneCallListener phoneCallListener;
public class PlayerBinder extends Binder
{
Player getService()
{
return Player.this;
}
}
@SuppressWarnings("deprecation")
@Override
public void onCreate()
{
playerThread = new PlayerThread();
playerThread.start();
telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
phoneCallListener = new PhoneCallListener();
telephonyManager.listen(phoneCallListener, PhoneStateListener.LISTEN_CALL_STATE);
startForeground(1, createNotification());
WakeLockManager.acquireWakeLock(this);
WifiLockManager.acquireWifiLock(this);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
return START_NOT_STICKY;
}
@Override
public IBinder onBind(Intent intent)
{
return playerBinder;
}
@Override
public void onDestroy()
{
playerThread.shutdown();
telephonyManager.listen(phoneCallListener, PhoneStateListener.LISTEN_NONE);
WakeLockManager.releaseWakeLock();
WifiLockManager.releaseWifiLock();
}
public int getProgress()
{
return playerThread.getProgress();
}
private Notification createNotification() {
Intent notificationIntent = new Intent(this, Main.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
Notification.Builder builder = new Notification.Builder(this)
.setContentTitle(getString(R.string.app_name))
.setContentText(getString(R.string.app_running))
.setSmallIcon(R.drawable.notif_icon)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.notif_icon))
.setContentIntent(pendingIntent);
return builder.build();
}
private class PlayerThread extends Thread
{
private AudioTrack player;
private volatile boolean running = true;
private volatile boolean playing = true;
private DatagramSocket socket;
private DatagramPacket packet;
private short[] pcmFrame = new short[Audio.FRAME_SIZE];
private byte[] encodedFrame;
private AtomicInteger progress = new AtomicInteger(0);
public void run()
{
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
while(isRunning())
{
init();
while(isPlaying())
{
try
{
socket.receive(packet); //<--- Problem is Here
}
catch(SocketException e) //Due to socket.close()
{
break;
}
catch(IOException e)
{
Log.error(getClass(), e);
}
if(AudioSettings.getEchoState()==AudioSettings.ECHO_OFF && IP.contains(packet.getAddress()))
continue;
if(AudioSettings.useSpeex()==AudioSettings.USE_SPEEX)
{
Speex.decode(encodedFrame, encodedFrame.length, pcmFrame);
player.write(pcmFrame, 0, Audio.FRAME_SIZE);
}
else
{
player.write(encodedFrame, 0, Audio.FRAME_SIZE_IN_BYTES);
}
progress.incrementAndGet();
}
player.stop();
player.release();
synchronized(this)
{
try
{
if(isRunning())
wait();
}
catch(InterruptedException e)
{
Log.error(getClass(), e);
}
}
}
}
private void init()
{
try
{
player = new AudioTrack(
AudioManager.STREAM_MUSIC,
Audio.SAMPLE_RATE,
AudioFormat.CHANNEL_OUT_MONO,
Audio.ENCODING_PCM_NUM_BITS,
Audio.TRACK_BUFFER_SIZE,
AudioTrack.MODE_STREAM);
switch(CommSettings.getCastType())
{
case CommSettings.BROADCAST:
socket = new DatagramSocket(CommSettings.getPort());
socket.setBroadcast(true);
break;
case CommSettings.MULTICAST:
socket = new MulticastSocket(CommSettings.getPort());
((MulticastSocket) socket).joinGroup(CommSettings.getMulticastAddr());
break;
case CommSettings.UNICAST:
socket = new DatagramSocket(CommSettings.getPort());
break;
}
if(AudioSettings.useSpeex()==AudioSettings.USE_SPEEX)
encodedFrame = new byte[Speex.getEncodedSize(AudioSettings.getSpeexQuality())];
else
encodedFrame = new byte[Audio.FRAME_SIZE_IN_BYTES];
packet = new DatagramPacket(encodedFrame, encodedFrame.length);
player.play();
}
catch(IOException e)
{
Log.error(getClass(), e);
}
}
private synchronized boolean isRunning()
{
return running;
}
private synchronized boolean isPlaying()
{
return playing;
}
public synchronized void pauseAudio()
{
playing = false;
try
{
if(socket instanceof MulticastSocket)
((MulticastSocket) socket).leaveGroup(CommSettings.getMulticastAddr());
socket.close();
}
catch (IOException e)
{
Log.error(getClass(), e);
}
}
public synchronized void resumeAudio()
{
playing = true;
notify();
}
private synchronized void shutdown()
{
pauseAudio();
running = false;
notify();
}
public int getProgress()
{
return progress.intValue();
}
}
private class PhoneCallListener extends PhoneStateListener
{
@Override
public void onCallStateChanged (int state, String incomingNumber)
{
if(state==TelephonyManager.CALL_STATE_OFFHOOK)
playerThread.pauseAudio();
else if(state==TelephonyManager.CALL_STATE_IDLE)
playerThread.resumeAudio();
}
}
}
WakeLockManager.java
import android.content.Context;
import android.os.PowerManager;
public class WakeLockManager {
private static PowerManager.WakeLock wakeLock;
public static final int PROXIMITY_SCREEN_OFF_WAKE_LOCK = 32;
public static void acquireWakeLock(Context context) {
if (wakeLock == null) {
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "pttdroid::WakeLock");
}
if (!wakeLock.isHeld()) {
wakeLock.acquire();
}
}
public static void releaseWakeLock() {
if (wakeLock != null && wakeLock.isHeld()) {
wakeLock.release();
wakeLock = null;
}
}
}
I used PowerManager.WakeLock and WifiManager.WifiLock wifi Lock, I tried to set timeouts for receive out of desperation, but nothing helped, I tried to change the sound type for AudioTrack and it didn't work either. Please ask if you have any questions, I will be extremely grateful for any advice.
Upvotes: 0
Views: 28