This is the receiver that I have created. The issue is that it does not give me any new values. I feel like it does not receive anything. How can I make myself receive something, why isn't it working here? I did it the same way for battery level and it worked. Finally, when I figure out how to receive something, how am I to get the WIFI bars ( I think if I make this thing return something then the WIFI bars will make more sense).
final BroadcastReceiver mWifiReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
final WifiManager wifi = (WifiManager)context.getSystemService(Context.WIFI_SERVICE);
int state = wifi.getWifiState();
if(state == WifiManager.WIFI_STATE_ENABLED) {
List<ScanResult> results = wifi.getScanResults();
for (ScanResult result : results) {
if(result.BSSID.equals(wifi.getConnectionInfo().getBSSID())) {
int level = WifiManager.calculateSignalLevel(wifi.getConnectionInfo().getRssi(),
result.level);
int difference = level * 100 / result.level;
if(difference >= 100)
signalStrength = 4;
else if(difference >= 75)
signalStrength = 3;
else if(difference >= 50)
signalStrength = 2;
else if(difference >= 25)
signalStrength = 1;
}
}
}
}
};
boolean mRegisteredWifiReceiver = false;
Of course I handled the functions not seen here for registering, unregistering, and calling.
Here is how I did that:
public void onVisibilityChanged(boolean visible) {
super.onVisibilityChanged(visible);
if (visible) {
registerReceiver();
registerWifiReceiver();
// registerBatteryReceiver();
// Update time zone in case it changed while we weren't visible.
mTime.clear(TimeZone.getDefault().getID());
mTime.setToNow();
invalidate();
} else {
unregisterReceiver();
unRegisterWifiReceiver();
//unRegisterBatteryReceiver();
}
}
private void registerWifiReceiver() {
if (mRegisteredWifiReceiver)
return;
mRegisteredWifiReceiver = true;
IntentFilter filter = new IntentFilter(WifiManager.RSSI_CHANGED_ACTION);
WatchFaceService.this.registerReceiver(mWifiReceiver, filter);
}
private void unRegisterWifiReceiver() {
if (!mRegisteredWifiReceiver)
return;
mRegisteredWifiReceiver = false;
WatchFaceService.this.unregisterReceiver(mWifiReceiver);
}
Related
After connecting with paired devices, Bluetooth is not taking his Mic, instead it is taking mobile's Mic
Below is my code
public abstract class BluetoothHeadsetUtils {
private Context mContext;
private BluetoothAdapter mBluetoothAdapter;
private BluetoothHeadset mBluetoothHeadset;
private BluetoothDevice mConnectedHeadset;
private AudioManager mAudioManager;
private boolean mIsCountDownOn;
private boolean mIsStarting;
private boolean mIsOnHeadsetSco;
private boolean mIsStarted;
ExminatingHelper exminatingHelper = ExminatingHelper.getInstance();
private static final String TAG = "BluetoothHeadsetUtils";
/**
* Constructor
*
* #param context
*/
public BluetoothHeadsetUtils(Context context) {
mContext = context;
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
}
/**
* Call this to start BluetoothHeadsetUtils functionalities.
*
* #return The return value of startBluetooth() or startBluetooth11()
*/
public boolean start() {
if (!mIsStarted) {
mIsStarted = true;
mIsStarted = startBluetooth();
/*if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
mIsStarted = startBluetooth();
} else {
System.out.println("");
// mIsStarted = startBluetooth11();
}*/
}
return mIsStarted;
}
/**
* Should call this on onResume or onDestroy.
* Unregister broadcast receivers and stop Sco audio connection
* and cancel count down.
*/
public void stop() {
if (mIsStarted) {
mIsStarted = false;
stopBluetooth();
/*if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
stopBluetooth();
} else {
System.out.println("");
// stopBluetooth11();
}*/
}
}
/**
* #return true if audio is connected through headset.
*/
public boolean isOnHeadsetSco() {
return mIsOnHeadsetSco;
}
public abstract void onHeadsetDisconnected();
public abstract void onHeadsetConnected();
public abstract void onScoAudioDisconnected();
public abstract void onScoAudioConnected();
#SuppressWarnings("deprecation")
private boolean startBluetooth() {
Log.d(TAG, "startBluetooth"); //$NON-NLS-1$
// Device support bluetooth
if (mBluetoothAdapter != null) {
if (mAudioManager.isBluetoothScoAvailableOffCall()) {
mContext.registerReceiver(mBroadcastReceiver,
new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED));
mIsCountDownOn = true;
// mCountDown repeatedly tries to start bluetooth Sco audio connection.
mCountDown.start();
// need for audio sco, see mBroadcastReceiver
mIsStarting = true;
return true;
}
}
return false;
}
private CountDownTimer mCountDown = new CountDownTimer(10000, 1000) {
#SuppressWarnings("synthetic-access")
#Override
public void onTick(long millisUntilFinished) {
// When this call is successful, this count down timer will be canceled.
mAudioManager.startBluetoothSco();
Log.d(TAG, "\nonTick start bluetooth Sco"); //$NON-NLS-1$
}
#SuppressWarnings("synthetic-access")
#Override
public void onFinish() {
// Calls to startBluetoothSco() in onStick are not successful.
// Should implement something to inform user of this failure
mIsCountDownOn = false;
Log.d(TAG, "\nonFinish fail to connect to headset audio"); //$NON-NLS-1$
}
};
private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
#SuppressWarnings({"deprecation", "synthetic-access"})
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
int getRecrodingDevice = exminatingHelper.getRecordingDevice();
if (action.equals(BluetoothDevice.ACTION_ACL_CONNECTED)) {
mConnectedHeadset = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
BluetoothClass bluetoothClass = mConnectedHeadset.getBluetoothClass();
if (bluetoothClass != null) {
// Check if device is a headset. Besides the 2 below, are there other
// device classes also qualified as headset?
int deviceClass = bluetoothClass.getDeviceClass();
if (deviceClass == BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE
|| deviceClass == BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET
|| deviceClass == BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES
|| deviceClass == BluetoothClass.Device.AUDIO_VIDEO_LOUDSPEAKER
) {
// start bluetooth Sco audio connection.
// Calling startBluetoothSco() always returns faIL here,
// that why a count down timer is implemented to call
// startBluetoothSco() in the onTick.
mAudioManager.setMode(AudioManager.MODE_IN_CALL);
mIsCountDownOn = true;
mCountDown.start();
// override this if you want to do other thing when the device is connected.
onHeadsetConnected();
}
}
Log.d(TAG, mConnectedHeadset.getName() + " connected"); //$NON-NLS-1$
} else if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) {
Log.d(TAG, "Headset disconnected"); //$NON-NLS-1$
if (mIsCountDownOn) {
mIsCountDownOn = false;
mCountDown.cancel();
}
// override this if you want to do other thing when the device is disconnected.
onHeadsetDisconnected();
} else if (action.equals(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED) && getRecrodingDevice != 2) {
int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE,
AudioManager.SCO_AUDIO_STATE_ERROR);
if (state == AudioManager.SCO_AUDIO_STATE_CONNECTED) {
mIsOnHeadsetSco = true;
if (mIsStarting) {
// When the device is connected before the application starts,
// ACTION_ACL_CONNECTED will not be received, so call onHeadsetConnected here
mIsStarting = false;
onHeadsetConnected();
}
if (mIsCountDownOn) {
mIsCountDownOn = false;
mCountDown.cancel();
}
// override this if you want to do other thing when Sco audio is connected.
onScoAudioConnected();
Log.d(TAG, "Sco connected"); //$NON-NLS-1$
} else if (state == AudioManager.SCO_AUDIO_STATE_DISCONNECTED) {
Log.d(TAG, "Sco disconnected"); //$NON-NLS-1$
// Always receive SCO_AUDIO_STATE_DISCONNECTED on call to startBluetooth()
// which at that stage we do not want to do anything. Thus the if condition.
if (!mIsStarting) {
mIsOnHeadsetSco = false;
// Need to call stopBluetoothSco(), otherwise startBluetoothSco()
// will not be successful.
mAudioManager.stopBluetoothSco();
// override this if you want to do other things when Sco audio is disconnected.
onScoAudioDisconnected();
}
}
}
}
};
private void stopBluetooth() {
Log.d(TAG, "stopBluetooth"); //$NON-NLS-1$
if (mIsCountDownOn) {
mIsCountDownOn = false;
mCountDown.cancel();
}
// Need to stop Sco audio connection here when the app
// change orientation or close with headset still turns on.
mContext.unregisterReceiver(mBroadcastReceiver);
mAudioManager.stopBluetoothSco();
mAudioManager.setMode(AudioManager.MODE_NORMAL);
}
}
}
This works well when using the phone in a normal fashion. However, it does not detect the presence of a Bluetooth headset and still uses the phone's own microphone even when the headset is plugged in.
Here's a clip of mine, there was this Bluetooth receiver class shared on SO, but it didn't work well with me (long story short, don't use the (state == AudioManager.SCO_AUDIO_STATE_DISCONNECTED) because when I trigger it via clicking the button, there's usually a false positive).
Try following the logs..
and on
onHeadsetConnected();
like
private void onHeadsetConnected(){
speech.startListening(theIntent);
}
while to capture when you have "disconnected", instead of counting SCO_AUDIO_STATE_DISCONNECTED, just capture onError, onPartialResult, onResult and recheck whether the device is still there .. as so, or .. you know .. recheck it when you need to listen to it again instead of when it's done ..
mBluetoothHeadset.getConnectionState(mConnectedHeadset) == BluetoothHeadset.STATE_CONNECTED
And I do this to ensure I'm connecting to the right headset (that has a mic!)
if (mBluetoothHeadset.getConnectedDevices().size()>0) {
mConnectedHeadset = null;
for (int i=0;i<mBluetoothHeadset.getConnectedDevices().size(); i ++){
int deviceClass = mBluetoothHeadset.getConnectedDevices().get(i).getBluetoothClass().getDeviceClass();
switch (deviceClass){
case BluetoothClass.Device.Major.PHONE:
case BluetoothClass.Device.Major.AUDIO_VIDEO:
case BluetoothClass.Device.AUDIO_VIDEO_MICROPHONE:
case BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE:
mAudioManager.setMode(AudioManager.MODE_IN_CALL);
mConnectedHeadset = mBluetoothHeadset.getConnectedDevices().get(i);
registerReceiver(mHeadsetBroadcastReceiver,
new IntentFilter(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED));
return;
}
}
}
Hope this helps you / or someone .. since I tried to implement that class, way too much of a hassle, so I just took parts of it into my activity and use what I needed (definitely didn't need support for old android)
I am playing MIDI notes using this library as follows:
handler.postDelayed(new Runnable() {
ShortMessage message;
#Override
public void run() {
{
MidiEvent event = midiEvents.get(index[0]);
if (index[0] < midiEvents.size() - 1) {
delta = midiEvents.get(index[0] + 1).getDelta();
time[0] = timeFactor * midiEvents.get(index[0] + 1).getDelta();
mTotalMidiTime += time[0];
int noteValue;
int NOTE_STATUS;
if (event instanceof NoteOn) {
noteValue = ((NoteOn) event).getNoteValue();
NOTE_STATUS = NOTE_ON;
if (index[0] != 0) {
if (delta != 0) {
Intent intent = new Intent();
intent.setAction(Constants.SCROLL_RECYCLERVIEW);
localBroadcastManager.sendBroadcast(intent);
}
}
} else {
noteValue = ((NoteOff) event).getNoteValue();
NOTE_STATUS = NOTE_OFF;
}
try {
message = new ShortMessage(NOTE_STATUS, 2, noteValue,
127);
} catch (Exception e) {
e.printStackTrace();
}
Intent intent = new Intent();
intent.setAction(Constants.ACTION_SEEK);
localBroadcastManager.sendBroadcast(intent);
if (message != null)
recv.send(message, -1);
index[0]++;
} else {
index[0] = 0;
time[0] = 1;
mTotalMidiTime = mMinimumTime;
delta = 0;
}
handler.postDelayed(this, time[0]);
}
}
}, 0);
With each NoteOn event I am smooth scrolling a RecyclerView and updating a Seekbar using a LocalBroadcastManager
My problem is that playback is fine when UI operations are not performed but playback and UI get completely out of sync as soon as multiple MIDI notes (chords) are played in very quick succession. It would be appreciated if any performance improvements are suggested for the same. I have already tried performing the UI operations in runOnUiThread and also launching a new Handler for UI operations.
My BroadcastReceiver is as follows:
BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String actionType = intent.getAction();
switch (actionType) {
case Constants.SCROLL_RECYCLERVIEW:
Handler handler = new Handler();
handler.post(new Runnable() {
#Override
public void run() {
mNotesRecycler.smoothScrollBy(pixels, 0);
}
});
break;
case Constants.ACTION_SEEK:
Handler seekHandler = new Handler();
seekHandler.post(new Runnable() {
#Override
public void run() {
mPinchSeekBar.setSelectedCentreValue(mTotalMidiTime);
mCurrentTime.setText(timeInMinutes((int) mTotalMidiTime));
}
});
break;
}
}
};
Besides the optimizations you can do, I think the problem itself is RecyclerView's smoothScroll is more a method you call sometimes to do a fancy scroll rather than bomb it with requests that cause it to constantly recompute the running animation.
One thing you can try is to write yourself a simple scroll handler that calls mRecyclerView.scrollTo() that does the scroll without animation but I guess it's going to be more reliable.
Try something like this
Handler mHandler = new Handler();
int mPosition, mTargetPosition;
#IntRange(from = 20, to = 100)
final int INTERVAL = 50; // try with 50 ms or a little lower
Runnable mTimerScroll = new Runnable() {
public void run() {
if (mPosition != mTargetPosition) {
if (mPosition < mTargetPosition) {
mPosition += mDelta;
if (mPosition > mTargetPosition) mPosition = mTargetPosition;
}
if (mPosition > mTargetPosition) {
mPosition -= mDelta;
if (mPosition < mTargetPosition) mPosition = mTargetPosition;
}
mRecyclerView.scrollTo(mPosition, 0);
}
// repeat every 50ms
mTimerScroll.post(mRunnable, INTERVAL);
}
}
And then you start it
void startTimer() {
stop(); // prevent double start
mHandler.post(mTimerScroll);
}
void stopTimer() {
mHandler.removeCallbacks(mTimerScroll);
}
void scroll(int target) {
mTargetPosition = target;
}
void scrollBy(int pixels) {
scroll(mPosition + pixels);
}
I don't know the specifics of your app but it might work.
About optimization, you are using a lot of stuff there that can or cannot be necessary depending on the specifics of your library, etc, but if there are no different threads or services involved you could avoid the LocalBroadcast thing and all the handler.post() as everything is already on the UI thread (handler.post just posts a runnable to the thread where the handler was created, that in your case is the UI thread, so it doesn't do anything)
I have a problem on Android 7 that not support the broadcast event "android.hardware.action.NEW_PICTURE" longer. I write now for Android 7 a JobService but it will not fire when a Picture is shot by the internal camera.
I don't know what is the problem, can everybody help me.
If any example source in the www that's for Android 7 and JobService for the replacement the broadcast "android.hardware.action.NEW_PICTURE" .
Thanks for help !
Here is my example Code:
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public class ZNJobService extends JobService {
private static Zlog log = new Zlog(ZNJobService.class.getName());
static final Uri MEDIA_URI = Uri.parse("content://" + MediaStore.AUTHORITY + "/");
static final int ZNJOBSERVICE_JOB_ID = 777;
static JobInfo JOB_INFO;
#RequiresApi(api = Build.VERSION_CODES.N)
public static boolean isRegistered(Context pContext){
JobScheduler js = pContext.getSystemService(JobScheduler.class);
List<JobInfo> jobs = js.getAllPendingJobs();
if (jobs == null) {
log.INFO("ZNJobService not registered ");
return false;
}
for (int i = 0; i < jobs.size(); i++) {
if (jobs.get(i).getId() == ZNJOBSERVICE_JOB_ID) {
log.INFO("ZNJobService is registered :-)");
return true;
}
}
log.INFO("ZNJobService is not registered");
return false;
}
public static void registerJob(Context pContext){
Log.i("ZNJobService","ZNJobService init");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N ) {
if (! isRegistered(pContext)) {
Log.i("ZNJobService", "JobBuilder executes");
log.INFO("JobBuilder executes");
JobInfo.Builder builder = new JobInfo.Builder(ZNJOBSERVICE_JOB_ID, new ComponentName(pContext, ZNJobService.class.getName()));
// Look for specific changes to images in the provider.
builder.addTriggerContentUri(new JobInfo.TriggerContentUri(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS));
// Also look for general reports of changes in the overall provider.
//builder.addTriggerContentUri(new JobInfo.TriggerContentUri(MEDIA_URI, 0));
JOB_INFO = builder.build();
log.INFO("JOB_INFO created");
JobScheduler scheduler = (JobScheduler) pContext.getSystemService(Context.JOB_SCHEDULER_SERVICE);
int result = scheduler.schedule(JOB_INFO);
if (result == JobScheduler.RESULT_SUCCESS) {
log.INFO(" JobScheduler OK");
} else {
log.ERROR(" JobScheduler fails");
}
}
} else {
JOB_INFO = null;
}
}
#RequiresApi(api = Build.VERSION_CODES.N)
#Override
public boolean onStartJob(JobParameters params) {
log.INFO("onStartJob");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
if (params.getJobId() == ZNJOBSERVICE_JOB_ID) {
if (params.getTriggeredContentAuthorities() != null) {
for (Uri uri : params.getTriggeredContentUris()) {
log.INFO("JobService Uri=%s",uri.toString());
}
}
}
}
this.jobFinished(params,false);
return false;
}
#Override
public boolean onStopJob(JobParameters params) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
log.INFO("onStopJob");
}
return true;
}
}
In the below code you can pass the flag immediate as false for normal operation (i.e. schedule within system guidelines for an app's good behaviour). When your app's main activity starts you can pass immediate as true to force a quick retrieval of media content changes.
You should run code in the onStartJob() method in a background job. (As shown below.)
If you only want to receive media from the camera and not other sources you should just filter out URI's based on their path. So only include "*/DCIM/*". (I haven't put this in the below code though.)
Also the Android job scheduler has a policy where it denies your service if it detects over abuse. Maybe your tests have caused this in your app, so just uninstall and reinstall to reset it.
public class ZNJobService extends JobService {
//...
final Handler workHandler = new Handler();
Runnable workRunnable;
//...
public static void registerJob(Context context, boolean immediate) {
final JobInfo jobInfo = createJobInfo(context, immediate);
final JobScheduler js = context.getSystemService(JobScheduler.class);
final int result = js.schedule(jobInfo);
if (result == JobScheduler.RESULT_SUCCESS) {
log.INFO(" JobScheduler OK");
} else {
log.ERROR(" JobScheduler fails");
}
}
private static JobInfo createJobInfo(Context context, boolean immediate) {
final JobInfo.Builder b =
new JobInfo.Builder(
ZNJOBSERVICE_JOB_ID, new ComponentName(context, ZNJobService.class));
// Look for specific changes to images in the provider.
b.addTriggerContentUri(
new JobInfo.TriggerContentUri(
MediaStore.Images.Media.INTERNAL_CONTENT_URI,
JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS));
b.addTriggerContentUri(
new JobInfo.TriggerContentUri(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS));
if (immediate) {
// Get all media changes within a tenth of a second.
b.setTriggerContentUpdateDelay(1);
b.setTriggerContentMaxDelay(100);
} else {
// Wait at least 15 minutes before checking content changes.
// (Change this as necessary.)
b.setTriggerContentUpdateDelay(15 * 60 * 1000);
// No longer than 2 hours for content changes.
// (Change this as necessary.)
b.setTriggerContentMaxDelay(2 * 60 * 60 * 1000);
}
return b.build();
}
#Override
public boolean onStartJob(final JobParameters params) {
log.INFO("onStartJob");
if (params.getTriggeredContentAuthorities() != null && params.getTriggeredContentUris() != null) {
// Process changes to media content in a background thread.
workRunnable = new Runnable() {
#Override
public void run() {
yourMethod(params.getTriggeredContentUris());
// Reschedule manually. (The 'immediate' flag might have changed.)
jobFinished(params, /*reschedule*/false);
scheduleJob(ZNJobService.this, /*immediate*/false);
}};
Postal.ensurePost(workHandler, workRunnable);
return true;
}
// Only reschedule the job.
scheduleJob(this, /*immediate*/false);
return false;
}
#Override
public boolean onStopJob(final JobParameters params) {
if (workRunnable != null) {
workHandler.removeCallbacks(workRunnable);
workRunnable = null;
}
return false;
}
private static void yourMethod(Uri[] uris) {
for (Uri uri : uris) {
log.INFO("JobService Uri=%s", uri.toString());
}
}
}
I'm trying to implement a fast-forward and rewind actions using PlaybackControlsRow using Leanback library for Android TV, however I can't find any method to detect a long press on these buttons. My current implementation is simple, only does seeking for 10 seconds on one click:
private void setupRows() {
final ClassPresenterSelector ps = new ClassPresenterSelector();
final PlaybackControlsRowPresenter playbackControlsRowPresenter =
new PlaybackControlsRowPresenter(new DescriptionPresenter());
playbackControlsRowPresenter.setOnActionClickedListener(action -> {
if (action.getId() == playPauseAction.getId()) {
togglePlayback(playPauseAction.getIndex() == PlayPauseAction.PLAY);
} else if (action.getId() == fastForwardAction.getId()) {
fastForward();
return;
} else if (action.getId() == rewindAction.getId()) {
rewind();
return;
}
if (action instanceof PlaybackControlsRow.MultiAction) {
((PlaybackControlsRow.MultiAction) action).nextIndex();
notifyChanged(action);
}
});
ps.addClassPresenter(PlaybackControlsRow.class, playbackControlsRowPresenter);
ps.addClassPresenter(ListRow.class, new ListRowPresenter());
rowsAdapter = new ArrayObjectAdapter(ps);
updatePlaybackControlsRow();
setAdapter(rowsAdapter);
}
private void fastForward() {
((PlaybackActivity) getActivity()).onFragmentFastForward();
final int currentTime = ((PlaybackActivity) getActivity()).getPosition();
playbackControlsRow.setCurrentTime(currentTime);
}
private void rewind() {
((PlaybackActivity) getActivity()).onFragmentRewind();
final int currentTime = ((PlaybackActivity) getActivity()).getPosition();
playbackControlsRow.setCurrentTime(currentTime);
}
In PlaybackActivity:
public void onFragmentFastForward() {
// Fast forward 10 seconds.
videoView.seekTo(videoView.getCurrentPosition() + (10 * 1000));
}
public void onFragmentRewind() {
videoView.seekTo(videoView.getCurrentPosition() - (10 * 1000));
}
Is it possible to implement fast-forward and rewind on long press of actions, like key-up/key-down events on the action buttons?
After looking for other solutions, seems that PlaybackControlsRowPresenter is designed in the way that it should have no long presses, but instead increasing/reducing speed by the number of clicks on fast-forward/rewind buttons. It can be clearly seen from internal constructor implementation of PlaybackControlsRowPresenter.FastForwardAction and PlaybackControlsRowPresenter.RewindAction classes:
/**
* Constructor
* #param context Context used for loading resources.
* #param numSpeeds Number of supported fast forward speeds.
*/
public FastForwardAction(Context context, int numSpeeds) {
So, as the result, my solution for now is increasing/reducing a speed by each click on the fast-forward/rewind buttons (which is done on UI by default). After that, when I click on play - it just resumes video from the seeked point.
UPDATE (updated parts of code):
private void setupRows() {
final ClassPresenterSelector ps = new ClassPresenterSelector();
final PlaybackControlsRowPresenter playbackControlsRowPresenter =
new PlaybackControlsRowPresenter(new DescriptionPresenter());
playbackControlsRowPresenter.setOnActionClickedListener(action -> {
if (action.getId() == playPauseAction.getId()) {
togglePlayback(playPauseAction.getIndex() == PlayPauseAction.PLAY);
((PlaybackControlsRow.MultiAction) action).nextIndex();
notifyChanged(action);
} else if (action.getId() == fastForwardAction.getId()) {
if (currentSpeed <= MAX_SPEED) {
currentSpeed++;
showTogglePlayback(false, true);
if (currentSpeed < 0) {
prevRewind();
} else if (currentSpeed > 0) {
nextFastForward();
} else {
currentSpeed++;
prevRewind();
nextFastForward();
}
((PlaybackActivity) getActivity()).seek(currentSpeed);
}
} else if (action.getId() == rewindAction.getId()) {
if (currentSpeed >= MIN_SPEED) {
currentSpeed--;
showTogglePlayback(false, true);
if (currentSpeed > 0) {
prevFastForward();
} else if (currentSpeed < 0) {
nextRewind();
} else {
currentSpeed--;
prevFastForward();
nextRewind();
}
((PlaybackActivity) getActivity()).seek(currentSpeed);
}
} else if (action.getId() == R.id.lb_control_picture_in_picture &&
PlaybackActivity.supportsPictureInPicture(getActivity())) {
getActivity().enterPictureInPictureMode();
}
});
ps.addClassPresenter(PlaybackControlsRow.class, playbackControlsRowPresenter);
ps.addClassPresenter(ListRow.class, new ListRowPresenter());
rowsAdapter = new ArrayObjectAdapter(ps);
updatePlaybackControlsRow();
setAdapter(rowsAdapter);
}
private void prevFastForward() {
fastForwardAction.setIndex(fastForwardAction.getIndex() - 1);
notifyChanged(fastForwardAction);
}
private void nextFastForward() {
fastForwardAction.nextIndex();
notifyChanged(fastForwardAction);
}
private void prevRewind() {
rewindAction.setIndex(rewindAction.getIndex() - 1);
notifyChanged(rewindAction);
}
private void nextRewind() {
rewindAction.nextIndex();
notifyChanged(rewindAction);
}
I am using the following code in wpa_supplicant for getting the signal strength of wifi in Android. I am able to get linkspeed but signal strength is always showing -110dB, although router is 1 meter away.
Code:
if ((os_strcasecmp(cmd, "rssi") == 0) || (os_strcasecmp(cmd, "rssi-approx") == 0)) {
struct iwreq wrq;
struct iw_statistics stats;
signed int rssi;
wpa_printf(MSG_DEBUG, ">>>. DRIVER AWEXT RSSI ");
wrq.u.data.pointer = (caddr_t) &stats;
wrq.u.data.length = sizeof(stats);
wrq.u.data.flags = 1; /* Clear updated flag */
os_strncpy(wrq.ifr_name, drv->wext->ifname, IFNAMSIZ);
if (ioctl(drv->wext->ioctl_sock, SIOCGIWSTATS, &wrq) < 0) {
perror("ioctl[SIOCGIWSTATS]");
ret = -1;
} else {
if (stats.qual.updated & IW_QUAL_DBM) {
/* Values in dBm, stored in u8 with range 63 : -192 */
rssi = ( wrq.u.qual.level > 63 ) ?
wrq.u.qual.level - 0x100 :
wrq.u.qual.level;
} else {
rssi = wrq.u.qual.level;
}
if (drv->ssid_len != 0 && drv->ssid_len < buf_len) {
os_memcpy((void *) buf, (void *) (drv->ssid),
drv->ssid_len );
ret = drv->ssid_len;
ret += snprintf(&buf[ret], buf_len-ret,
" rssi %d\n", rssi);
if (ret < (int)buf_len) {
return( ret );
}
ret = -1;
}
}
}
Following code will provide the RSSI value of wifi strength...
hope this will help you.....
public class Wifi2 extends Activity{
Context context;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
context=this;
}
#Override
public void onResume() {
super.onResume();
//Note: Not using RSSI_CHANGED_ACTION because it never calls me back.
IntentFilter rssiFilter = new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
this.registerReceiver(myRssiChangeReceiver, rssiFilter);
WifiManager wifiMan=(WifiManager)context.getSystemService(Context.WIFI_SERVICE);
wifiMan.startScan();
}
#Override
public void onPause() {
super.onPause();
this.unregisterReceiver(myRssiChangeReceiver);
}
/**
* Broadcast receiver to update
* s
*/
private BroadcastReceiver myRssiChangeReceiver
= new BroadcastReceiver(){
#Override
public void onReceive(Context arg0, Intent arg1) {
WifiManager wifiMan=(WifiManager)context.getSystemService(Context.WIFI_SERVICE);
wifiMan.startScan();
int newRssi = wifiMan.getConnectionInfo().getRssi();
Toast.makeText(context, ""+newRssi, Toast.LENGTH_SHORT).show();
}};
}