I am trying to make a custom layout for incoming and outgoing calls, and while the call is in the progress a specific image will be shown which has to stay visible even when user covers proximity sensor. I tried with wakelock but no success, now I am using proximity sensor which will just hide buttons and leave image to be displayed. This is working on some phones and all of the emulators but there are few samsung and sony phones that simply turn off the screen when close to sensor. This is my code for proximity sensor:
#Override
protected void onPause() {
super.onPause();
}
#Override
protected void onResume() {
super.onResume();
Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
sensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL);
}
#Override
public void onSensorChanged(SensorEvent event) {
float distance = event.values[0];
if(distance < 4){
buttonsLayout.setVisibility(View.INVISIBLE);
}
else {
buttonsLayout.setVisibility(View.VISIBLE);
}
}
Any help is appreciated.
Edit:
I am making calls with these:
android.telephony.PhoneStateListener
android.telephony.TelephonyManager
com.android.internal.telephony.ITelephony (using reflection)
This is how I accept calls:
private void acceptCall() {
timerLayout.setVisibility(View.VISIBLE);
answerButton.setVisibility(View.GONE);
startTime = SystemClock.uptimeMillis();
customHandler.postDelayed(updateTimerThread, 0);
try {
Runtime.getRuntime().exec("input keyevent " +
Integer.toString(KeyEvent.KEYCODE_HEADSETHOOK));
} catch (IOException e) {
String enforcedPerm = "android.permission.CALL_PRIVILEGED";
Intent btnDown = new Intent(Intent.ACTION_MEDIA_BUTTON).putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_HEADSETHOOK));
Intent btnUp = new Intent(Intent.ACTION_MEDIA_BUTTON).putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_HEADSETHOOK));
sendOrderedBroadcast(btnDown, enforcedPerm);
sendOrderedBroadcast(btnUp, enforcedPerm);
}
}
Related
My app already does speech recognition. A user told me it didn't work with a Bluetooth headset. I was able to, mostly, get speech recognition working over the Bluetooth headset (thanks to another Stack Overflow contributor, no thanks to the official Android documentation).
There is one annoying problem, however: when switching to use the Bluetooth headset, it can obliterate audio output briefly during the switchover. In particular, it can sometimes omit the beep that ordinarily prompts the user for speech recognition.
My current workaround is to put in a one-second delay, after the Bluetooth headset has been connected to the SCO audio channel, before doing speech recognition.
My question: is there a more reliable method of avoiding this conflict?
static AudioManager sAudioManager;
static BluetoothHeadset sBluetoothHeadset;
static BluetoothDevice sBluetoothDevice;
static public void initBluetooth(Context pContext)
{
sAudioManager = (AudioManager) pContext.getSystemService(Context.AUDIO_SERVICE);
// Register to get notifications about Bluetooth profiles
sBluetoothAdapter.getProfileProxy(
pContext, new BluetoothProfileListener(), BluetoothProfile.HEADSET);
// Register to receive notification when the headset is dis/connected
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED);
pContext.registerReceiver(
new BluetoothHeadsetBroadcastReceiver(), intentFilter);
}
public static void startSpeechRecognition()
{
sAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
sAudioManager.startBluetoothSco();
sAudioManager.setBluetoothScoOn(true);
sBluetoothHeadset.startVoiceRecognition(sBluetoothDevice);
}
public static void stopSpeechRecognition()
{
sBluetoothHeadset.stopVoiceRecognition(sBluetoothDevice);
sAudioManager.stopBluetoothSco();
sAudioManager.setBluetoothScoOn(false);
sAudioManager.setMode(AudioManager.MODE_NORMAL);
}
static public void doSpeechRecognition(Context pContext)
{
SpeechRecognizer sr = SpeechRecognizer.createSpeechRecognizer(pContext);
Intent intent =
new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent.putExtra(
RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
sr.startListening(intent);
}
static public class BluetoothHeadsetBroadcastReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context pContext, Intent pIntent)
{
int state = pIntent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1);
if (state == AudioManager.SCO_AUDIO_STATE_CONNECTED)
{
// CURRENT WORKAROUND
// Delay speech recognition to avoid obliterating beep prompt
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{
};
doSpeechRecognition(pContext);
}
}
}
static public class BluetoothProfileListener implements BluetoothProfile.ServiceListener
{
#Override
public void onServiceConnected(int pProfile, BluetoothProfile pProxy)
{
sBluetoothHeadset = (BluetoothHeadset) pProxy;
List<BluetoothDevice> devices = pProxy.getConnectedDevices();
int numDevices = devices.size();
if (numDevices > 0)
{
BluetoothDevice device = devices.get(0);
sBluetoothDevice = device;
}
}
}
Is it possible to control playback of the Spotify app from within another Android app? I'm only looking for track skipping functionality (forward and backward).
I'm aware of the Spotify Android SDK, but it seems to only allow skipping of tracks played by the SDK:
com.spotify.sdk.android.playback.NativeSpotifyException: Failed SpPlaybackSkipToPrev with error code 14 (The operation is not supported if the device is not the active playback device)
To clarify, both the actual Spotify app, and my own app are running on the same device
Here's how to do it:
This will try to play/pause Spotify. If it's not running it will start it and make it start playing.
public void nextSong() {
int keyCode = KeyEvent.KEYCODE_MEDIA_NEXT;
if (!isSpotifyRunning()) {
startMusicPlayer();
}
Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON);
intent.setPackage("com.spotify.music");
synchronized (this) {
intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, keyCode));
getContext().sendOrderedBroadcast(intent, null);
intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, keyCode));
getContext().sendOrderedBroadcast(intent, null);
}
}
public void playPauseMusic() {
int keyCode = KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE;
if (!mAudioManager.isMusicActive() && !isSpotifyRunning()) {
startMusicPlayer();
}
Intent i = new Intent(Intent.ACTION_MEDIA_BUTTON);
i.setPackage("com.spotify.music");
synchronized (this) {
i.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, keyCode));
getContext().sendOrderedBroadcast(i, null);
i.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, keyCode));
getContext().sendOrderedBroadcast(i, null);
}
}
private void startMusicPlayer() {
Intent startPlayer = new Intent(Intent.ACTION_MAIN);
startPlayer.setPackage("com.spotify.music");
startPlayer.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getContext().startActivity(startPlayer);
if (mMusicPlayerStartTimer != null) {
mMusicPlayerStartTimer.cancel();
}
mMusicPlayerStartTimer = new Timer("MusicPlayerStartTimer", true);
mMusicPlayerStartTimer.schedule(new MusicPlayerStartTimerTask(), DateUtils.SECOND_IN_MILLIS, DateUtils.SECOND_IN_MILLIS);
}
private boolean isSpotifyRunning() {
Process ps = null;
try {
String[] cmd = {
"sh",
"-c",
"ps | grep com.spotify.music"
};
ps = Runtime.getRuntime().exec(cmd);
ps.waitFor();
return ps.exitValue() == 0;
} catch (IOException e) {
Log.e(DEBUG_TAG, "Could not execute ps", e);
} catch (InterruptedException e) {
Log.e(DEBUG_TAG, "Could not execute ps", e);
} finally {
if (ps != null) {
ps.destroy();
}
}
return false;
}
private class MusicPlayerStartTimerTask extends TimerTask {
#Override
public void run() {
if (isSpotifyRunning()) {
playPauseMusic(null);
cancel();
}
}
}
EDIT: Added full example code
Yes, you can control playback using the RemoteController classes, or if using Lollipop, the MediaController classes, or if supporting L and earlier, then the MediaControllerCompat classes.
Then perform dispatchMediaButtonEvent() with KEYCODE_MEDIA_NEXT.
Quick answer - No, this isn't possible.
I'm simply trying to record accelerometer data and write a file in sdcard with a button click. While running the app in my Nexus S (with 4.1.2), it freezes after a minute. I tried to run it in Galaxy Nexus phone and it works smoothly. For some reasons I have to work in Nexus S. Can anyone suggest me what might be the reason of crashing. I tried to see the log, but it does not through any error message.
Here's my code:
final SensorEventListener mySensorEventListener = new SensorEventListener() {
public void onSensorChanged(SensorEvent sensorEvent) {
if (sensorEvent.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
xAxis_lateralA = sensorEvent.values[0];
yAxis_longitudinalA = sensorEvent.values[1];
zAxis_verticalA = sensorEvent.values[2]; // TODO apply the acceleration changes to your application.
textView.append("\nACC_x = "+ xAxis_lateralA + ", ACC_y = "+yAxis_longitudinalA+ ", ACC_z = " + zAxis_verticalA);
acc += "\n"+miliSec()+", "+xAxis_lateralA + ", "+ yAxis_longitudinalA+", "+zAxis_verticalA;
try {
File myFile = new File("/sdcard/acc.txt");
myFile.createNewFile();
FileOutputStream fOut = new FileOutputStream(myFile);
OutputStreamWriter myOutWriter = new OutputStreamWriter(fOut);
myOutWriter.append(acc);
myOutWriter.close();
fOut.close();
} catch (Exception e) {
Toast.makeText(getBaseContext(), e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO Auto-generated method stub
}
};
startButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Toast.makeText(getBaseContext(),"Done writing SD 'acc.txt'",Toast.LENGTH_SHORT).show();
sm = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
int sensorType = Sensor.TYPE_ACCELEROMETER;
sm.registerListener(mySensorEventListener,sm.getDefaultSensor(sensorType), SensorManager.SENSOR_DELAY_NORMAL);
}// onClick
}); // btnWriteSDFile
stopButton = (Button) findViewById(R.id.stopButton);
stopButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
int sensorType = Sensor.TYPE_ACCELEROMETER;
sm.unregisterListener(mySensorEventListener, sm.getDefaultSensor(sensorType));
Toast.makeText(getBaseContext(), "Stopped Recording",Toast.LENGTH_SHORT).show();
finish();
}// onClick
}); // btnstopButton
Issue is due to the way your writing values to text file.
You are opening/writing/closiing the file for everytime you get sensor reading.
Even for Sensor reading frequency of 50Hz it takes lot computation,writing these in text for 50 times/second is not efficient.
Use BufferedWriter ,it gives better performance.
I have written the following lines to record accelerometer data in a file with a button click
startButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
final SensorEventListener mySensorEventListener = new SensorEventListener() {
public void onSensorChanged(SensorEvent sensorEvent) {
if (sensorEvent.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
xAxis_lateralA = sensorEvent.values[0];
yAxis_longitudinalA = sensorEvent.values[1];
zAxis_verticalA = sensorEvent.values[2]; // TODO apply the acceleration changes to your application.
textView.append("\nACC_x = "+ xAxis_lateralA + ", ACC_y = "+yAxis_longitudinalA+ ", ACC_z = " + zAxis_verticalA);
acc+="\n"+xAxis_lateralA + ", "+ yAxis_longitudinalA+", "+zAxis_verticalA;
try {
File myFile = new File("/sdcard/acc.txt");
myFile.createNewFile();
FileOutputStream fOut = new FileOutputStream(myFile);
OutputStreamWriter myOutWriter =
new OutputStreamWriter(fOut);
myOutWriter.append(acc);
myOutWriter.close();
fOut.close();
Toast.makeText(getBaseContext(),
"Done writing SD 'acc.txt'",
Toast.LENGTH_SHORT).show();
} catch (Exception e) {
Toast.makeText(getBaseContext(), e.getMessage(),
Toast.LENGTH_SHORT).show();
}
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO Auto-generated method stub
}
};
// write on SD card file data in the text box
sm = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
int sensorType = Sensor.TYPE_ACCELEROMETER;
sm.registerListener(mySensorEventListener,sm.getDefaultSensor(sensorType), SensorManager.SENSOR_DELAY_NORMAL);
}// onClick
});
Now I want it to stop recording the data with another button click. For example -
stopButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
int sensorType = Sensor.TYPE_ACCELEROMETER;
sm.unregisterListener(listener, sensor)
}// onClick
}); // btnstopButton
}
Wanted to use unregisterListener but most of the time it is saying deprecated.
Can anyone help please?
The documentation says that using the methods associated with SensorListener are deprecated, and to use SensorEventListener instead. Your code snippet should not throw a deprecated warning, but if you use SensorListener, it would.
I think you want to declare your SensorEventListener object outside of the onClick() method so you can unregister it in the other onClick() method:
sm.unregisterListener(mySensorEventListener, sensorType);
That's the method signature you want to use according to the docs.
I have to perform a task of creating an Android Application that will pick all the calls, play a pre-recorded voice to the other party and cut the phone. Is it possible?
Skeleton code is most welcome.
No, you are not able to play back anything other way than via loud speaker. Therefore you will not be able to write "silent auto answering" app or anything like that. It is intentional I guess, to not let app "speak" in behalf of the user the way he will not know that
This is the code I did write:
public class AutoAnswerIntentService extends IntentService {
public AutoAnswerIntentService() {
super("AutoAnswerIntentService");
}
#Override
protected void onHandleIntent(Intent intent) {
Context context = getBaseContext();
// Load preferences
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
BluetoothHeadset bh = null;
if (prefs.getBoolean("headset_only", false)) {
bh = new BluetoothHeadset(this, null);
}
// Let the phone ring for a set delay
try {
Thread.sleep(Integer.parseInt(prefs.getString("delay", "2")) * 1000);
} catch (InterruptedException e) {
// We don't really care
}
// Check headset status right before picking up the call
if (prefs.getBoolean("headset_only", false) && bh != null) {
if (bh.getState() != BluetoothHeadset.STATE_CONNECTED) {
bh.close();
return;
}
bh.close();
}
// Make sure the phone is still ringing
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
if (tm.getCallState() != TelephonyManager.CALL_STATE_RINGING) {
return;
}
// Answer the phone
try {
answerPhoneAidl(context);
}
catch (Exception e) {
e.printStackTrace();
Log.d("AutoAnswer","Error trying to answer using telephony service. Falling back to headset.");
answerPhoneHeadsethook(context);
}
// Enable the speakerphone
if (prefs.getBoolean("use_speakerphone", false)) {
enableSpeakerPhone(context);
}
return;
}
private void enableSpeakerPhone(Context context) {
AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
audioManager.setSpeakerphoneOn(true);
}
private void answerPhoneHeadsethook(Context context) {
// Simulate a press of the headset button to pick up the call
Intent buttonDown = new Intent(Intent.ACTION_MEDIA_BUTTON);
buttonDown.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_HEADSETHOOK));
context.sendOrderedBroadcast(buttonDown, "android.permission.CALL_PRIVILEGED");
// froyo and beyond trigger on buttonUp instead of buttonDown
Intent buttonUp = new Intent(Intent.ACTION_MEDIA_BUTTON);
buttonUp.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_HEADSETHOOK));
context.sendOrderedBroadcast(buttonUp, "android.permission.CALL_PRIVILEGED");
}
#SuppressWarnings("unchecked")
private void answerPhoneAidl(Context context) throws Exception {
// Set up communication with the telephony service (thanks to Tedd's Droid Tools!)
TelephonyManager tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
Class c = Class.forName(tm.getClass().getName());
Method m = c.getDeclaredMethod("getITelephony");
m.setAccessible(true);
ITelephony telephonyService;
telephonyService = (ITelephony)m.invoke(tm);
// Silence the ringer and answer the call!
telephonyService.silenceRinger();
telephonyService.answerRingingCall();
}
}