CompanionDeviceService gets destroyed right after creation - android

I have simple activity with function that when called displays ble pairing request. After user confirms, startObservingDevicePresence("Some Mac address") is called. That successfully triggers CompanionDeviceService and I see logs that device appeared in range, but right after that onDestroy is called. App continues to run and there are no errors in logs. Has anybody used successfully these new android 12 api's (https://developer.android.com/guide/topics/connectivity/companion-device-pairing#keep-awake)?
MainActivity:
public class MainActivity extends ReactActivity {
private static final int SELECT_DEVICE_REQUEST_CODE = 42;
private static CompanionDeviceManager deviceManager;
private static AssociationRequest pairingRequest;
private static BluetoothDeviceFilter deviceFilter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(null);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
deviceManager = getSystemService(CompanionDeviceManager.class);
}
}
public void start() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
deviceFilter = new BluetoothDeviceFilter.Builder()
.build();
pairingRequest = new AssociationRequest.Builder()
.addDeviceFilter(deviceFilter)
.build();
deviceManager.associate(pairingRequest,
new CompanionDeviceManager.Callback() {
#Override
public void onDeviceFound(IntentSender chooserLauncher) {
try {
startIntentSenderForResult(chooserLauncher,
SELECT_DEVICE_REQUEST_CODE, null, 0, 0, 0);
} catch (IntentSender.SendIntentException e) {
e.printStackTrace();
}
}
#Override
public void onFailure(CharSequence charSequence) {
}
},
null);
}
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
try {
deviceManager.startObservingDevicePresence("Some MAC address");
} catch(DeviceNotAssociatedException e) {}
}
}
}
}
CompanionService:
#RequiresApi(VERSION_CODES.S)
public class BleCompanionDeviceService extends CompanionDeviceService {
private static final String TAG = "BleReceiver";
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onDeviceAppeared(#NonNull String s) {
Log.d(TAG, "DEVICE APPEARED INTO RANGE");
}
#Override
public void onDeviceDisappeared(#NonNull String s) {
Log.d(TAG, "DEVICE DISAPPEARED");
}
#Override
public void onDestroy() {
Log.d(TAG, "SERVICE DESTROYED");
}
}

This seems to be a race condition happening in CompanionDeviceManager, Android 13 should have fixed it.

Related

How to save state of a progressbar when app is killed?

I am building a simple downloader app, with a pause/resume button. When I click on pause button and kill the app the download progress isn't shown anymore, after I open the app again. I want to save the download progress state even if the app is killed. Can anyone help me with this? I'm building the app using download manager pro library from github.
here's the code:
Activity Class:
public class MainActivity extends AppCompatActivity {
String[] permissions = {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
};
public static final int REQUEST_ID_MULTIPLE_PERMISSIONS = 100;
EditText edt_url;
Button btn_download;
TextView fileNametv, ProgressbarTv;
private MyDownloadService mService;
ProgressBar progressBar;
String filename, url;
/* UrlFileNameListener listener;*/
Integer progress;
MyReceiver receiver;
public static MainActivity instance;
/* RecyclerView recyclerView;
List<Model> downloadList;
LinearLayoutManager manager;
DownloadAdapter adapter;
// ImageView pausebtn;
int position;*/
File myDirectory;
Boolean mBound = false;
Button pause_btn;
int tasktoken;
/* Model model;
Parcelable mListState;
private final String KEY_RECYCLER_STATE = "recycler_state";
private final String KEY_LIST_STATE = "list_state";*/
private ServiceConnection mServiceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
mBound = true;
MyDownloadService.LocalBinder localBinder = (MyDownloadService.LocalBinder) iBinder;
mService = localBinder.getService();
}
#Override
public void onServiceDisconnected(ComponentName componentName) {
mBound = false;
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/* if(savedInstanceState!=null){
mListState = savedInstanceState.getParcelable(KEY_RECYCLER_STATE);
downloadList =savedInstanceState.getParcelableArrayList(KEY_LIST_STATE);
} */
setContentView(R.layout.activity_main);
edt_url = findViewById(R.id.edt_url);
btn_download = findViewById(R.id.btn_download);
pause_btn = findViewById(R.id.pause_resume);
/*recyclerView = findViewById(R.id.recycler_view);
downloadList = new ArrayList<>();
manager = new LinearLayoutManager(this);
adapter = new DownloadAdapter(downloadList, this);
recyclerView.setLayoutManager(manager);
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(),
manager.getOrientation());
recyclerView.addItemDecoration(dividerItemDecoration);
recyclerView.setAdapter(adapter);*/
fileNametv = findViewById(R.id.download_file_name);
ProgressbarTv = findViewById(R.id.progress_tv);
progressBar = findViewById(R.id.download_progress);
// pausebtn = findViewById(R.id.pause_resume);
instance = this;
/* if (progress!= null && filename != null) {
savedInstanceState.putInt("progress", progress);
savedInstanceState.putString("filename",filename);
// savedInstanceState.putString("filename", model.getFileName());
// savedInstanceState.putParcelable("list",mListState);
}*/
receiver = new MyReceiver();
btn_download.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getDownloadProcess();
}
});
pause_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mService.pauseDownload(tasktoken);
}
});
LocalBroadcastManager.getInstance(this)
.registerReceiver(receiver,
new IntentFilter("download"));
if (checkAndRequestPermissions()) {
myDirectory = new File(Environment.getExternalStorageDirectory() + "/" + "RITSDownloads2");
if (!myDirectory.exists()) {
myDirectory.mkdir();
}
}
}
#Override
protected void onStart() {
super.onStart();
Intent intent = new Intent(this,MyDownloadService.class);
bindService(intent,mServiceConnection,Context.BIND_AUTO_CREATE);
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("progress", progress);
outState.putString("filename",filename);
/* mListState = manager.onSaveInstanceState();
outState.putParcelable(KEY_RECYCLER_STATE,mListState);
outState.putParcelableArrayList(KEY_LIST_STATE, (ArrayList<? extends Parcelable>) adapter.getDownloadList());*/
}
#Override
protected void onPause() {
super.onPause();
//mListState = manager.onSaveInstanceState();
}
#Override
protected void onResume() {
super.onResume();
// manager.onRestoreInstanceState(mListState);
}
#Override
public void onBackPressed() {
progress = progressBar.getProgress();
super.onBackPressed();
}
/* #Override
public void onRestoreInstanceState(Bundle savedInstanceState, PersistableBundle persistentState) {
super.onRestoreInstanceState(savedInstanceState, persistentState);
manager.onRestoreInstanceState(mListState);
savedInstanceState.getParcelable(KEY_RECYCLER_STATE);
savedInstanceState.getParcelableArrayList(KEY_LIST_STATE);
}
*/
private void getDownloadProcess() {
url = edt_url.getText().toString();
filename = URLUtil.guessFileName(url, null, null);
//listener.setUrl(url,filename);
edt_url.setText("");
/* model = new Model();
model.setFileName(filename);
downloadList.add(model);
adapter.notifyDataSetChanged();*/
fileNametv.setText(filename);
Intent intent = new Intent(MainActivity.this, MyDownloadService.class);
intent.putExtra("filename", filename);
intent.putExtra("url", url);
intent.setAction(DownloadActions.ACTION.Download_ACTION);
startService(intent);
}
public class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
progress = intent.getIntExtra("progress", 1);
ReportStructure reportStructure = MyDownloadService.downloadManagerPro.singleDownloadStatus(intent.getIntExtra("tasktoken",1));
tasktoken = intent.getIntExtra("tasktoken",1);
// model.setProgress(progress);
/*int position = downloadList.indexOf(model);
DownloadAdapter.DownloadHolder holder = getDownloadHolder(position);
holder.progressBar.setProgress(progress);*/
progressBar.setProgress(progress);
}
}
/* public DownloadAdapter.DownloadHolder getDownloadHolder(int position) {
return (DownloadAdapter.DownloadHolder) recyclerView.findViewHolderForLayoutPosition(position);
}
*/
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
savedInstanceState.getInt("progress");
savedInstanceState.getString("filename");
/* Log.d("savedInstancestate",savedInstanceState.toString());
//savedInstanceState.getInt("position");
if(savedInstanceState!=null){
List<Model> downloadList = savedInstanceState.getParcelableArrayList(KEY_LIST_STATE);
adapter = new DownloadAdapter(downloadList,this);
}
*/
}
private boolean checkAndRequestPermissions() {
if (ContextCompat.checkSelfPermission(this, permissions[0]) != PackageManager.PERMISSION_GRANTED
&& ContextCompat.checkSelfPermission(this, permissions[1]) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, permissions, REQUEST_ID_MULTIPLE_PERMISSIONS);
return false;
} else {
return true;
}
}
#Override
public void onRequestPermissionsResult(int requestCode,
#NonNull String permissions[], #NonNull int[] grantResults) {
String TAG = "LOG_PERMISSION";
Log.d(TAG, "Permission callback called-------");
switch (requestCode) {
case REQUEST_ID_MULTIPLE_PERMISSIONS: {
Map<String, Integer> perms = new HashMap<>();
// Initialize the map with both permissions
perms.put(this.permissions[0], PackageManager.PERMISSION_GRANTED);
perms.put(this.permissions[1], PackageManager.PERMISSION_GRANTED);
// Fill with actual results from user
if (grantResults.length > 0) {
for (int i = 0; i < permissions.length; i++)
perms.put(permissions[i], grantResults[i]);
// Check for both permissions
if (perms.get(this.permissions[0]) == PackageManager.PERMISSION_GRANTED
&& perms.get(this.permissions[1]) == PackageManager.PERMISSION_GRANTED
) {
Log.d(TAG, "Phone state and storage permissions granted");
// process the normal flow
//else any one or both the permissions are not granted
//TODO Do your stuff here after permissions granted
} else {
Log.d(TAG, "Some permissions are not granted ask again ");
//permissions is denied (this is the first time, when "never ask again" is not checked) so ask again explaining the usage of permissions
// //shouldShowRequestPermissionRationale will return true
//show the dialog or snackbar saying its necessary and try again otherwise proceed with setup.
if (ActivityCompat.shouldShowRequestPermissionRationale(this, this.permissions[0]) ||
ActivityCompat.shouldShowRequestPermissionRationale(this, this.permissions[1])) {
showDialogOK("Phone state and storage permissions required for this app",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
checkAndRequestPermissions();
break;
case DialogInterface.BUTTON_NEGATIVE:
// proceed with logic by disabling the related features or quit the app.
break;
}
}
});
}
//permissions is denied (and never ask again is checked)
//shouldShowRequestPermissionRationale will return false
else {
Toast.makeText(this, "Go to settings and enable permissions", Toast.LENGTH_LONG)
.show();
//proceed with logic by disabling the related features or quit the app.
}
}
}
}
}
}
private void showDialogOK(String message, DialogInterface.OnClickListener okListener) {
new AlertDialog.Builder(this)
.setMessage(message)
.setPositiveButton("OK", okListener)
.setNegativeButton("Cancel", okListener)
.create()
.show();
}
}
Service Class:
public class MyDownloadService extends Service implements DownloadManagerListener {
private static final String LOG_TAG = "tag";
public static DownloadManagerPro downloadManagerPro;
File myDirectory;
int taskToken;
String name;
Intent notificationIntent;
Notification notification;
PendingIntent pendingIntent;
private IBinder binder = new LocalBinder();
#Nullable
#Override
public IBinder onBind(Intent intent) {
return binder;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent.getAction().equals(DownloadActions.ACTION.Download_ACTION)) {
Log.d(LOG_TAG, "Received Start Foreground Intent");
}
name = intent.getStringExtra("filename");
final String url = intent.getStringExtra("url");
Log.d(LOG_TAG, name);
Log.d(LOG_TAG, url);
downloadManagerPro = new DownloadManagerPro(this.getApplicationContext());
downloadManagerPro.init("RITSDownloads2/", 16, this);
myDirectory = new File(Environment.getExternalStorageDirectory() + "/" + "RITSDownloads2");
if (!myDirectory.exists()) {
myDirectory.mkdir();
}
taskToken = downloadManagerPro.addTask(name, url, 16, true, true);
Log.d(LOG_TAG, String.valueOf(taskToken));
try {
downloadManagerPro.startDownload(taskToken);
notificationIntent = new Intent(this, MainActivity.class);
notificationIntent.setAction(DownloadActions.ACTION.Download_ACTION);
pendingIntent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
notification = new NotificationCompat.Builder(this)
.setContentTitle("Downloading")
.setTicker("Rits Download")
.setContentText(name)
.setSmallIcon(android.R.drawable.stat_sys_download)
.setContentIntent(pendingIntent)
.setOngoing(true)
.build();
startForeground(DownloadActions.NOTIFICATION_ID.FOREGROUND_SERVICE,
notification);
// stopForeground(true);
// stopSelf();
} catch (IOException e) {
e.printStackTrace();
}
return START_STICKY;
}
#Override
public void OnDownloadStarted(long taskId) {
Log.d(LOG_TAG, "DownloadStarted");
}
#Override
public void OnDownloadPaused(long taskId) {
}
#Override
public void onDownloadProcess(long taskId, double percent, long downloadedLength) {
final int progress = (int) percent;
final int taskToken = (int) taskId;
// int position = positions.get(taskToken);
notification = new NotificationCompat.Builder(this)
.setContentTitle("Downloading")
.setTicker("Rits Download")
.setContentText(name)
.setSmallIcon(android.R.drawable.stat_sys_download)
.setContentIntent(pendingIntent)
.setOngoing(true)
.setColor(ContextCompat.getColor(this, R.color.colorPrimary))
.setProgress(100, progress, false)
.build();
startForeground(DownloadActions.NOTIFICATION_ID.FOREGROUND_SERVICE,
notification);
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("progress", progress);
intent.setAction("download");
intent.putExtra("tasktoken",taskToken);
ReportStructure structure = downloadManagerPro.singleDownloadStatus(taskToken);
String name =structure.name;
intent.putExtra("name",name);
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);
}
#Override
public void OnDownloadFinished(long taskId) {
}
#Override
public void OnDownloadRebuildStart(long taskId) {
}
#Override
public void OnDownloadRebuildFinished(long taskId) {
}
public void pauseDownload(int taskToken){
ReportStructure reportStructure = downloadManagerPro.singleDownloadStatus(taskToken);
if(reportStructure.state == TaskStates.DOWNLOADING){
downloadManagerPro.pauseDownload(taskToken);
} else if(reportStructure.state == TaskStates.PAUSED){
try {
downloadManagerPro.startDownload(taskToken);
} catch (IOException e) {
e.printStackTrace();
}
}
}
#Override
public void OnDownloadCompleted(long taskId) {
Log.d(LOG_TAG, "Download Complete");
/* MainActivity.instance.pausebtn.post(new Runnable() {
#Override
public void run() {
MainActivity.instance.pausebtn.setImageDrawable(getResources().getDrawable(R.drawable.ic_action_done));
}
});*/
notification = new NotificationCompat.Builder(this)
.setContentTitle("Download Complete")
.setTicker("Rits Download")
.setContentText(name)
.setSmallIcon(R.drawable.ic_action_done)
.setContentIntent(pendingIntent)
.setOngoing(true)
.setColor(ContextCompat.getColor(this, R.color.colorPrimary))
.build();
startForeground(DownloadActions.NOTIFICATION_ID.FOREGROUND_SERVICE,
notification);
}
#Override
public void connectionLost(long taskId) {
}
#Override
public void onTaskRemoved(Intent rootIntent) {
/* Intent restartService = new Intent(getApplicationContext(),this.getClass());
restartService.setPackage(getPackageName());
PendingIntent restartPendingIntent =PendingIntent.getService(getApplicationContext(), 1,restartService, PendingIntent.FLAG_ONE_SHOT);
AlarmManager myAlarmService = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
myAlarmService.set(
AlarmManager.ELAPSED_REALTIME,
SystemClock.elapsedRealtime() + 1000,
restartPendingIntent);*/
}
public class LocalBinder extends Binder{
public MyDownloadService getService(){
return MyDownloadService.this;
}
}
}
I don't know how you want to save the state but I do know that an activity has a onStop() method that you can override.
The onStop() method runs when the app is killed so I would imagine you would want to do your "saving" in this method.
As for saving something I believe you would want to use the SharedPreferences class. You can find more information about that here.
You can find the lifecycle of an activity here
hope this helps
Save the progress on SharedPreferences onDestroy() and retrieve it from there when activity is created.
Cache:
#Override
protected void onDestroy() {
super.onDestroy();
SharedPreferences sharedPreferences = getSharedPreferences("space_name", MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putInt("progress", progress).apply();
}
And retrieve:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SharedPreferences sharedPreferences = getSharedPreferences("space_name", MODE_PRIVATE);
progress = sharedPreferences.getInt("progress", 0); // 0 default value in case is empty
}

Open an app using voice recognition (PocketSphinx)

I want to create a voice recognition app in android and run it in service so i can use it even without in the app. So i looked for reference and i found in GitHub a demo app.
This is the site https://github.com/ihrupin/SpeechRecognitionService
I download the app and also i read the documentation, Yes it running well to me it also running in service, but i really want is for example if i said (open Facebook) it will open the installed Facebook app.
I'm newbie in using the PocketSphinx.
This is the MainActivity
public class MainActivity extends AppCompatActivity {
private static final int PERMISSIONS_REQUEST_RECORD_AUDIO = 1;
private static final String LOG_TAG = MainActivity.class.getSimpleName();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
((Button)findViewById(R.id.btn)).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.i(LOG_TAG, "onClick");
int permissionCheck = ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.RECORD_AUDIO);
if (permissionCheck == PackageManager.PERMISSION_DENIED) {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.RECORD_AUDIO}, PERMISSIONS_REQUEST_RECORD_AUDIO);
return;
}
startService(new Intent(MainActivity.this, VoiceService.class));
}
});
}
#Override
public void onRequestPermissionsResult(int requestCode,
String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == PERMISSIONS_REQUEST_RECORD_AUDIO) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
startService(new Intent(MainActivity.this, VoiceService.class));
} else {
finish();
}
}
}
}
This is my Service
public class VoiceService extends Service implements
RecognitionListener {
private static final String LOG_TAG = VoiceService.class.getSimpleName();
private static final String KWS_SEARCH = "wakeup";
private static final String KEYPHRASE = "lisa";
private SpeechRecognizer recognizer;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
int permissionCheck = ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.RECORD_AUDIO);
if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
runRecognizerSetup();
}
return super.onStartCommand(intent, flags, startId);
}
private void runRecognizerSetup() {
new AsyncTask<Void, Void, Exception>() {
#Override
protected Exception doInBackground(Void... params) {
try {
Assets assets = new Assets(VoiceService.this);
File assetDir = assets.syncAssets();
setupRecognizer(assetDir);
} catch (IOException e) {
return e;
}
return null;
}
#Override
protected void onPostExecute(Exception result) {
if (result != null) {
Log.i(LOG_TAG, "Failed to init recognizer ");
} else {
switchSearch(KWS_SEARCH);
}
}
}.execute();
}
#Override
public void onDestroy() {
super.onDestroy();
if (recognizer != null) {
recognizer.cancel();
recognizer.shutdown();
}
}
#Override
public void onPartialResult(Hypothesis hypothesis) {
if (hypothesis == null)
return;
String text = hypothesis.getHypstr();
if (text.contains(KEYPHRASE)) {
Toast.makeText(this, "onPartialResult text=" + text, Toast.LENGTH_SHORT).show();
switchSearch(KWS_SEARCH);
}
Log.i(LOG_TAG, "onPartialResult text=" +text);
}
#Override
public void onResult(Hypothesis hypothesis) {
if (hypothesis != null) {
String text = hypothesis.getHypstr();
Log.i(LOG_TAG, "onResult text=" +text);
}
}
#Override
public void onBeginningOfSpeech() {
Log.i(LOG_TAG, "onBeginningOfSpeech");
}
#Override
public void onEndOfSpeech() {
if (!recognizer.getSearchName().contains(KWS_SEARCH))
switchSearch(KWS_SEARCH);
Log.i(LOG_TAG, "onEndOfSpeech");
}
private void switchSearch(String searchName) {
Log.i(LOG_TAG, "switchSearch searchName = " + searchName);
recognizer.stop();
recognizer.startListening(searchName, 10000);
}
private void setupRecognizer(File assetsDir) throws IOException {
recognizer = SpeechRecognizerSetup.defaultSetup()
.setAcousticModel(new File(assetsDir, "en-us-ptm"))
.setDictionary(new File(assetsDir, "cmudict-en-us.dict"))
.setRawLogDir(assetsDir)
.setKeywordThreshold(1e-45f)
.setBoolean("-allphone_ci", true)
.getRecognizer();
recognizer.addListener(this);
recognizer.addKeyphraseSearch(KWS_SEARCH, KEYPHRASE);
}
#Override
public void onError(Exception error) {
Log.i(LOG_TAG, "onError " + error.getMessage());
}
#Override
public void onTimeout() {
switchSearch(KWS_SEARCH);
Log.i(LOG_TAG, "onTimeout");
}
}
This is BootReceiver
public class BootReceiver extends BroadcastReceiver {
private static final String LOG_TAG = BootReceiver.class.getSimpleName();
#Override
public void onReceive(Context context, Intent intent) {
Log.i(LOG_TAG, "onReceive");
if(intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)){
Log.i(LOG_TAG, "onReceive onBoot");
context.startService(new Intent(context, VoiceService.class));
}
}
}
I've researched about this topic and i found out that i must modify the grammar and the dictionary but i don't know how to do that. Any ideas?
If you want to modify the existing grammer and want to add your own words you have to modify it a little bit.
write this line in your recognizer setup method.
recognizer.addKeyphraseSearch("facebookPhrase", "Open Facebook");
To edit this example you can read about on official website here
https://cmusphinx.github.io/wiki/tutoriallm/

How to check if no beacons are available Android

I am trying to play around with Beacons and I have got this code:
By following this tutorial:
Activity2.java
public class Activity2 extends AppCompatActivity {
//String myString = MyViewClass.infoToPass;
public static final String TAG = "Airport";
TextView tvFooter;
private static final Map<String, List<String>> PLACES_BY_BEACONS;
// TODO: replace "<major>:<minor>" strings to match your own beacons.
static {
Map<String, List<String>> placesByBeacons = new HashMap<>();
placesByBeacons.put("22504:48827", new ArrayList<String>() {{
add("Heavenly Sandwiches");
// read as: "Heavenly Sandwiches" is closest
// to the beacon with major 22504 and minor 48827
add("Green & Green Salads");
// "Green & Green Salads" is the next closest
add("Mini Panini");
// "Mini Panini" is the furthest away
}});
placesByBeacons.put("648:12", new ArrayList<String>() {{
add("Mini Panini");
add("Green & Green Salads");
add("Heavenly Sandwiches");
}});
PLACES_BY_BEACONS = Collections.unmodifiableMap(placesByBeacons);
}
private List<String> placesNearBeacon(Beacon beacon) {
String beaconKey = String.format("%d:%d", beacon.getMajor(), beacon.getMinor());
if (PLACES_BY_BEACONS.containsKey(beaconKey)) {
return PLACES_BY_BEACONS.get(beaconKey);
}
return Collections.emptyList();
}
private BeaconManager beaconManager;
private Region region;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_2);
//updateCordinate("Just some random text");
Log.d(TAG, "onCreate");
beaconManager = new BeaconManager(this);
beaconManager.setRangingListener(new BeaconManager.RangingListener() {
#Override
public void onBeaconsDiscovered(Region region, List<Beacon> list) {
Log.d(TAG, "onBeaconsDiscovered");
if (!list.isEmpty()) {
Beacon nearestBeacon = list.get(0);
List<String> places = placesNearBeacon(nearestBeacon);
// TODO: update the UI here
Log.d(TAG, "Nearest places: " + places);
}
else{
// this line is not executing
Log.d(TAG, "You are not in area of beacons");
}
}
});
region = new Region("ranged region", UUID.fromString("B9407F30-F5F8-466E-AFF9-25556B57FE6D"), null, null);
}
#Override
protected void onResume() {
super.onResume();
Log.d(TAG, "onResume");
SystemRequirementsChecker.checkWithDefaultDialogs(this);
beaconManager.connect(new BeaconManager.ServiceReadyCallback() {
#Override
public void onServiceReady() {
Log.d(TAG, "onServiceReady");
beaconManager.startRanging(region);
}
});
}
#Override
protected void onPause() {
beaconManager.stopRanging(region);
Log.d(TAG, "onPause");
super.onPause();
}
//public void updateCordinate(String text1) {
// tvFooter = (TextView) findViewById(R.id.tvFooter);
// tvFooter.setText("Location is :" + myString);
// }
}
Now what I want it:
If I don't have any Beacons around me, I want to check for it and store that value in some variable so that I can use it in other class (non-activity class).
Also how do I check for range from it? (I know it's beyond the scope of this question but little idea will be welcomed)
//you may ignore the notification code, for my usage of Beacons in my app, i
//to send notification to my app even through the app is not open when a beacon //is in/out range.
public class EstimoteService extends Service implements BeaconManager.RangingListener, BeaconManager.MonitoringListener {
private static final int NOTIFICATION_ID = 123;
private static final Region ALL_ESTIMOTE_BEACONS_REGION = new Region("regionId", null, null, null);
private Beacon beaconFound;
private NotificationManager notificationManager;
private BeaconManager beaconManager;
#Override
public void onCreate() {
super.onCreate();
initResources();
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
notificationManager.cancel(NOTIFICATION_ID);
// Default values are 5s of scanning and 25s of waiting time to save CPU cycles.
// In order for this demo to be more responsive and immediate we lower down those values.
beaconManager.setBackgroundScanPeriod(TimeUnit.SECONDS.toMillis(1), 0);
beaconManager.connect(new BeaconManager.ServiceReadyCallback() {
#Override
public void onServiceReady() {
try {
beaconManager.startRanging(ALL_ESTIMOTE_BEACONS_REGION);
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
return START_NOT_STICKY;
}
private void initResources() {
notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
beaconManager = new BeaconManager(this);
beaconManager.setRangingListener(this);
beaconManager.setMonitoringListener(this);
}
#Override
public void onBeaconsDiscovered(Region region, List<Beacon> beacons) {
if (beaconFound == null) {
// Get the first available beaconFound
if (beacons.isEmpty())
return;
beaconFound = beacons.get(0);
final Region beaconRegion = new Region("regionId", beaconFound.getProximityUUID(), beaconFound.getMajor(), beaconFound.getMinor());
beaconManager.connect(new BeaconManager.ServiceReadyCallback() {
#Override
public void onServiceReady() {
try {
beaconManager.startMonitoring(beaconRegion);
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
}
}
#Override
public void onEnteredRegion(Region region, List<Beacon> beacons) {
postNotification("Entered region");
System.out.println("---> enter region");
}
#Override
public void onExitedRegion(Region region) {
postNotification("Exited region");
System.out.println("---> exit region");
}
private void postNotification(String msg) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setSmallIcon(R.drawable.beacon_gray).setContentTitle("XXX").setContentText(msg);
notificationManager.notify(NOTIFICATION_ID, builder.build());
}
}

My Android ActivityRecognition implementation is too slow

I used Google ActivityRecognitionApi for tracking whether i am walking or not.
But It seems too slow. What's the problem?
It doesn't related to internet connectivity.
[Walking.java]
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_walking);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(ActivityRecognition.API).addConnectionCallbacks(this)
.addOnConnectionFailedListener(this).build();
mGoogleApiClient.connect();
}
#Override
public void onConnected(Bundle bundle) {
Intent intent = new Intent(this, ActivityRecognitionService.class);
PendingIntent pendingIntent = PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
ActivityRecognition.ActivityRecognitionApi.requestActivityUpdates(mGoogleApiClient, 1000, pendingIntent);
}
#Override
public void onConnectionSuspended(int i) {
Toast.makeText(Walking.this, "Hello1", Toast.LENGTH_SHORT).show();
Log.e("Connection Failed : ", "Connection Failed");
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Toast.makeText(Walking.this, "Hello2", Toast.LENGTH_SHORT).show();
Log.e("Connection Failed : ", "Connection Failed");
}
[ActivityRecognitionService.java]
import java.util.List;
public class ActivityRecognitionService extends IntentService {
public static final String ACTION_IntentService = "com.example.android.skywalker.RESPONSE";
public static final String ACTIVITY_RESULT = "RESULT";
public Intent localIntent;
public ActivityRecognitionService() {
super("ActivityRecognitionService");
}
public ActivityRecognitionService(String name) {
super(name);
}
#Override
protected void onHandleIntent(Intent intent) {
if(ActivityRecognitionResult.hasResult(intent)) {
ActivityRecognitionResult result = ActivityRecognitionResult.extractResult(intent);
handleDetectedActivities(result.getProbableActivities());
}
}
private void handleDetectedActivities(List<DetectedActivity> probableActivities) {
int Flag = 0;
for(DetectedActivity activity : probableActivities) {
if(activity.getType() == DetectedActivity.ON_FOOT) {
Flag = 1;
if (activity.getConfidence() >= 50) Log.e("YES", "YES");
break;
}
}
//Intent intent = new Intent(ActivityRecognitionService.this, Walking.class);
if (Flag == 0) {
//localIntent = new Intent(Walking.BROADCAST_ACTION).putExtra(Walking.RESPONSE_STATUS, "YES");
Log.e("NO", "NO");
}
}
}
I don't think there is any problem with your code, it looks exactly the same as mine.
The normal rate for detection is 3 seconds -> 6 seconds if your "detectionIntervalMillis" value = 0.
But when you switch between 2 different activities (for example: from walking -> in the car....) it will take more, maybe 20s to 40s.

GoogleFit wasn't able to connect, so the request failed-Android

I have the following code where it does two main things.
It connects to google play services.
Inside the onConnected() method a service is started, by calling the startService(...) method.
When I run the program I get the following log message.
Connected!!!
Fit wasn't able to connect, so the request failed.
GoogleFitService destroyed.
Here is my code:
public class MainActivity extends ActionBarActivity {
public final static String TAG = "GoogleFitService";
private static final int REQUEST_OAUTH = 1;
private static final String AUTH_PENDING = "auth_state_pending";
private boolean authInProgress = false;
private GoogleApiClient mClient = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
buildFitnessClient();
}
private void buildFitnessClient() {
// Create the Google API Client
mClient = new GoogleApiClient.Builder(this)
.addApi(Fitness.API)
.addConnectionCallbacks(
new GoogleApiClient.ConnectionCallbacks() {
#Override
public void onConnected(Bundle bundle) {
Log.i(TAG, "Connected!!!");
// Now you can make calls to the Fitness APIs.
// Put application specific code here.
Intent service = new Intent(MainActivity.this,
GoogleFitService.class);
service.putExtra(GoogleFitService.SERVICE_REQUEST_TYPE,
GoogleFitService.TYPE_REQUEST_CONNECTION);
startService(service);
}
#Override
public void onConnectionSuspended(int i) {
if (i == GoogleApiClient.ConnectionCallbacks.CAUSE_NETWORK_LOST) {
Log.i(TAG, "Connection lost. Cause: Network Lost.");
} else if (i == GoogleApiClient.ConnectionCallbacks.CAUSE_SERVICE_DISCONNECTED) {
Log.i(TAG, "Connection lost. Reason: Service Disconnected");
}
}
}
)
.addOnConnectionFailedListener(
new GoogleApiClient.OnConnectionFailedListener() {
// Called whenever the API client fails to connect.
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.i(TAG, "Connection failed. Cause: " + result.toString());
if (!result.hasResolution()) {
// Show the localized error dialog
GooglePlayServicesUtil.getErrorDialog(result.getErrorCode(), MainActivity.this, 0).show();
return;
}
if (!authInProgress) {
try {
Log.i(TAG, "Attempting to resolve failed connection");
authInProgress = true;
result.startResolutionForResult(MainActivity.this, REQUEST_OAUTH);
} catch (IntentSender.SendIntentException e) {
Log.e(TAG, "Exception while starting resolution activity", e);
}
}
}
}
)
.build();
}
#Override
protected void onStart() {
super.onStart();
// Connect to the Fitness API
Log.i(TAG, "Connecting...");
mClient.connect();
Intent service = new Intent(this, GoogleFitService.class);
service.putExtra(GoogleFitService.SERVICE_REQUEST_TYPE, GoogleFitService.TYPE_REQUEST_CONNECTION);
startService(service);
}
#Override
protected void onStop() {
super.onStop();
if (mClient.isConnected()) {
mClient.disconnect();
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_OAUTH) {
authInProgress = false;
if (resultCode == RESULT_OK) {
// Make sure the app is not already connected or attempting to connect
if (!mClient.isConnecting() && !mClient.isConnected()) {
mClient.connect();
}
}
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(AUTH_PENDING, authInProgress);
}
}
And the second class is basically an Intent service. Maybe the mistake is here.
public class GoogleFitService extends IntentService {
public static final String TAG = "GoogleFitService";
private GoogleApiClient mGoogleApiFitnessClient;
private boolean mTryingToConnect = false;
public static final String SERVICE_REQUEST_TYPE = "requestType";
public static final int TYPE_GET_STEP_TODAY_DATA = 1;
public static final int TYPE_REQUEST_CONNECTION = 2;
public static final String HISTORY_INTENT = "fitHistory";
public static final String HISTORY_EXTRA_STEPS_TODAY = "stepsToday";
public static final String FIT_NOTIFY_INTENT = "fitStatusUpdateIntent";
public static final String FIT_EXTRA_CONNECTION_MESSAGE =
"fitFirstConnection";
public static final String FIT_EXTRA_NOTIFY_FAILED_STATUS_CODE =
"fitExtraFailedStatusCode";
public static final String FIT_EXTRA_NOTIFY_FAILED_INTENT =
"fitExtraFailedIntent";
#Override
public void onDestroy() {
Log.d(TAG, "GoogleFitService destroyed");
if (mGoogleApiFitnessClient.isConnected()) {
Log.d(TAG, "Disconecting Google Fit.");
mGoogleApiFitnessClient.disconnect();
}
super.onDestroy();
}
#Override
public void onCreate() {
super.onCreate();
buildFitnessClient();
Log.d(TAG, "GoogleFitService created");
}
public GoogleFitService() {
super("GoogleFitService");
}
#Override
protected void onHandleIntent(Intent intent) {
//Get the request type
int type = intent.getIntExtra(SERVICE_REQUEST_TYPE, 1);
//block until google fit connects. Give up after 10 seconds.
if (!mGoogleApiFitnessClient.isConnected()) {
mTryingToConnect = true;
mGoogleApiFitnessClient.connect();
//Wait until the service either connects or fails to connect
while (mTryingToConnect) {
try {
Thread.sleep(100, 0);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
if (mGoogleApiFitnessClient.isConnected()) {
if (type == TYPE_GET_STEP_TODAY_DATA) {
Log.d(TAG, "Requesting steps from Google Fit");
getStepsToday();
Log.d(TAG, "Fit update complete. Allowing Android to destroy
the service.");
} else if (type == TYPE_REQUEST_CONNECTION) {
}
} else {
//Not connected
Log.w(TAG, "Fit wasn't able to connect, so the request failed.");
}
}
private void getStepsToday() {
Calendar cal = Calendar.getInstance();
Date now = new Date();
cal.setTime(now);
long endTime = cal.getTimeInMillis();
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
long startTime = cal.getTimeInMillis();
final DataReadRequest readRequest = new DataReadRequest.Builder()
.read(DataType.TYPE_STEP_COUNT_DELTA)
.setTimeRange(startTime, endTime, TimeUnit.MILLISECONDS)
.build();
DataReadResult dataReadResult =
Fitness.HistoryApi.readData(mGoogleApiFitnessClient,
readRequest).await(1, TimeUnit.MINUTES);
DataSet stepData =
dataReadResult.getDataSet(DataType.TYPE_STEP_COUNT_DELTA);
int totalSteps = 0;
for (DataPoint dp : stepData.getDataPoints()) {
for (Field field : dp.getDataType().getFields()) {
int steps = dp.getValue(field).asInt();
totalSteps += steps;
}
}
publishTodaysStepData(totalSteps);
}
private void publishTodaysStepData(int totalSteps) {
Intent intent = new Intent(HISTORY_INTENT);
// You can also include some extra data.
intent.putExtra(HISTORY_EXTRA_STEPS_TODAY, totalSteps);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
private void buildFitnessClient() {
// Create the Google API Client
mGoogleApiFitnessClient = new GoogleApiClient.Builder(this)
.addApi(Fitness.API)
.addScope(new Scope(Scopes.FITNESS_BODY_READ_WRITE))
.addScope(new Scope(Scopes.FITNESS_ACTIVITY_READ_WRITE))
.addScope(new Scope(Scopes.FITNESS_LOCATION_READ_WRITE))
.addConnectionCallbacks(
new GoogleApiClient.ConnectionCallbacks() {
#Override
public void onConnected(Bundle bundle) {
Log.i(TAG, "Google Fit connected.");
mTryingToConnect = false;
Log.d(TAG, "Notifying the UI that we're
connected.");
notifyUiFitConnected();
}
#Override
public void onConnectionSuspended(int i) {
// If your connection to the sensor gets lost at
some point,
mTryingToConnect = false;
if (i ==
GoogleApiClient.ConnectionCallbacks.CAUSE_NETWORK_LOST) {
Log.i(TAG, "Google Fit Connection lost.
Cause:Network Lost.");
} else if (i ==
GoogleApiClient.ConnectionCallbacks.CAUSE_SERVICE_DISCONNECTED) {
Log.i(TAG, "Google Fit Connection lost.
Reason:Service Disconnected ");
}
}
}
)
.addOnConnectionFailedListener(
new GoogleApiClient.OnConnectionFailedListener() {
// Called whenever the API client fails to connect.
#Override
public void onConnectionFailed(ConnectionResult
result) {
mTryingToConnect = false;
notifyUiFailedConnection(result);
}
}
)
.build();
}
private void notifyUiFitConnected() {
Intent intent = new Intent(FIT_NOTIFY_INTENT);
intent.putExtra(FIT_EXTRA_CONNECTION_MESSAGE,
FIT_EXTRA_CONNECTION_MESSAGE);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
private void notifyUiFailedConnection(ConnectionResult result) {
Intent intent = new Intent(FIT_NOTIFY_INTENT);
intent.putExtra(FIT_EXTRA_NOTIFY_FAILED_STATUS_CODE,
result.getErrorCode());
intent.putExtra(FIT_EXTRA_NOTIFY_FAILED_INTENT, result.getResolution());
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
}
Any ideas what might went wrong? Thanks, Theo.
You need to access those detail from fit only when it connected .And Try this
public void buildFitnessClient() {
fitnessClient = new GoogleApiClient.Builder(context)
.addApi(Fitness.HISTORY_API)
.addApi(Fitness.SESSIONS_API)
.addApi(Fitness.RECORDING_API)
.addScope(new Scope(Scopes.FITNESS_BODY_READ_WRITE))
.addScope(new Scope(Scopes.FITNESS_ACTIVITY_READ_WRITE))
.addScope(new Scope(Scopes.FITNESS_LOCATION_READ_WRITE))
.addScope(new Scope(Scopes.FITNESS_NUTRITION_READ_WRITE))
.addConnectionCallbacks(
new GoogleApiClient.ConnectionCallbacks() {
#Override
public void onConnected(Bundle bundle) {
ReferenceWrapper.getInstance(context).setApiClient(fitnessClient);
((OnClientConnectListener) context).onclientConnected();
}
#Override
public void onConnectionSuspended(int i) {
}
})
.addOnConnectionFailedListener(
new GoogleApiClient.OnConnectionFailedListener() {
#Override
public void onConnectionFailed(
ConnectionResult result) {
if (!result.hasResolution()) {
GooglePlayServicesUtil.getErrorDialog(
result.getErrorCode(), context, 0)
.show();
return;
}
if (!authInProgress) {
try {
authInProgress = true;
result.startResolutionForResult(
context,
KeyConstant.REQUEST_OAUTH);
} catch (IntentSender.SendIntentException e) {
}
}
}
}).build();
}
And at first you need to register your application on google api console . Generate an outh2 client id from there and enable fitness api . Search for fitness Api in api Dashboard , and enable it.. And override OnActivityresult
in your Activity .
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == KeyConstant.REQUEST_OAUTH) {
fitnessHelper.setAuthInProgress(false);
if (resultCode == Activity.RESULT_OK) {
if (!fitnessHelper.isConnecting() && !fitnessHelper.isConnected()) {
fitnessHelper.connect();
}
}
}
}

Categories

Resources