I'm trying to copy my working TTS service code from app code to wear code but not work.
public class VoiceService extends Service implements
TextToSpeech.OnInitListener, TextToSpeech.OnUtteranceCompletedListener {
private final String TAG = "VoiceService";
private final int LONG_DURATION = 5000;
private final int SHORT_DURATION = 1200;
private TextToSpeech mTts;
private String messageTitle;
private String messageContext;
#Override
public void onCreate() {
Log.i(TAG, "onCreate");
try{
mTts = new TextToSpeech(this, this);
mTts.setOnUtteranceCompletedListener(this);
}
catch(Exception e){
e.printStackTrace();
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId){
Log.i(TAG, "onStartCommand");
messageTitle = ...
messageContext = ...
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onInit(int status) {
Log.i(TAG, "onInit & status = " + status);
if (status == TextToSpeech.SUCCESS) {
int result = mTts.setLanguage(Locale.getDefault());
Log.i(TAG, "TextToSpeech.SUCCESS");
if (result != TextToSpeech.LANG_MISSING_DATA
&& result != TextToSpeech.LANG_NOT_SUPPORTED
&& messageTitle.length() > 0
) {
Log.i(TAG, "messageTitle.length() > 0");
...
}
}
}
#Override
public void onUtteranceCompleted(String uttId) {
Log.i(TAG, "onUtteranceCompleted");
messageTitle = "";
messageContext = "";
stopSelf();
}
#Override
public void onDestroy() {
Log.i(TAG, "onDestroy");
// Text to Speech engine was attached
if (mTts != null) {
mTts.stop();
mTts.shutdown();
mTts = null;
}
super.onDestroy();
}
#Override
public IBinder onBind(Intent arg0) {
return null;
}
...
}
The log is simply as follows:
I/VoiceService: onCreate
I/VoiceService: onInit & status = -1
I/VoiceService: onStartCommand
I do not understand why onInit comes before onStartCommand, and failed, and the service stuck there forever...
I followed some threads and run the following code in mainactivity:
PackageManager pm = getPackageManager();
Intent installIntent = new Intent();
installIntent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
ResolveInfo resolveInfo = pm.resolveActivity( installIntent, PackageManager.MATCH_DEFAULT_ONLY );
if( resolveInfo == null ) {
// Not able to find he activity which should be started for this intent
Log.i(TAG, "Not able to find the activity which should be started for this intent");
} else {
Log.i(TAG, "try to install...");
startActivity( installIntent );
}
The log was as follow and I do not have idea to fix it:
Not able to find the activity which should be started for this intent
I am using Android Wear Emulator and I could not find TTS Enable button in Setting -> Accessibility menu. But under the menu, I found TalkBack(experimental), no idea what it is.
I had spent few days in this. a bit tired tonight. Please give me some direction of how to make TTS works in emulator.
Related
I need to know when the screen gets visible in the app how can I get to know which activity is related to that screen. Especially if I'm using another SDK to get login screens. So I need to know the activity name and package name of those screens.
Currently, I have a method inside my BaseActivity class to log activity names when it navigates between screens. But when I click login button it opens another screen which belongs to that third part SDK.
/**
* Logs the component with activity name and method
*
* #param tag
*/
private void logActivityInfo(String tag) {
mLogService.logScreenInfo(this.getClass().getSimpleName() + tag);
}
I think this can be solved if I have a trick to get activity name when I visible that screen. Because Android Profiler shows all activity names when moving between all screens. It would be great if someone can help me to find a way to solve this.
Maybe tracking activity life cycle events solves your problem here is some sample code.
public class MyApplication extends Application
implements Application.ActivityLifecycleCallbacks {
private int numStarted;
...
#Override
public void onCreate() {
...
registerActivityLifecycleCallbacks(this);
}
#Override
public void onActivityStarted(Activity activity) {
//some code
}
#Override
public void onActivityStopped(Activity activity) {
//some code
}
}
because they will run in your application context so tracking them there should list them as well.
You can use accessiblity service in Android to do this. I have a code thats working for me. You can try it out
package com.butterfly.instaliker;
public class WindowChangeDetectingService extends AccessibilityService
{
#Override
protected void onServiceConnected() {
super.onServiceConnected();
//Configure these here for compatibility with API 13 and below.
AccessibilityServiceInfo config = new AccessibilityServiceInfo();
config.eventTypes = AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
config.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;
if (Build.VERSION.SDK_INT >= 16)
//Just in case this helps
config.flags = AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
setServiceInfo(config);
}
#Override
public void onAccessibilityEvent(AccessibilityEvent event) {
if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
if (event.getPackageName() != null && event.getClassName() != null) {
ComponentName componentName = new ComponentName(
event.getPackageName().toString(),
event.getClassName().toString()
);
ActivityInfo activityInfo = tryGetActivity(componentName);
boolean isActivity = activityInfo != null;
if (isActivity)
if(componentName.flattenToShortString().equalsIgnoreCase(" com.instagram.android/com.instagram.mainactivity.MainActivity")){
scrollAndLike(event);
}
Log.i("CurrentActivity", componentName.flattenToShortString());
}
}
}
private void scrollAndLike(AccessibilityEvent event) {
AccessibilityNodeInfo nodeInfo = event.getSource();
Log.i("jude", "ACC::onAccessibilityEvent: nodeInfo=" + nodeInfo);
if (nodeInfo == null) {
return;
}
}
private ActivityInfo tryGetActivity(ComponentName componentName) {
try {
return getPackageManager().getActivityInfo(componentName, 0);
} catch (PackageManager.NameNotFoundException e) {
return null;
}
}
#Override
public void onInterrupt() {}
}
Your app should have the accessibility permission which you need the user to enable like
if (!isAccessibilitySettingsOn(getApplicationContext())) {
Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
startActivityForResult(intent,1000);
}
else{
startService(new Intent(this,WindowChangeDetectingService.class));
}
and
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == 1000){
startService(new Intent(this,WindowChangeDetectingService.class));
}
}
private boolean isAccessibilitySettingsOn(Context mContext) {
String TAG = "jude";
int accessibilityEnabled = 0;
final String service = getPackageName() + "/" + WindowChangeDetectingService.class.getCanonicalName();
try {
accessibilityEnabled = Settings.Secure.getInt(
mContext.getApplicationContext().getContentResolver(),
android.provider.Settings.Secure.ACCESSIBILITY_ENABLED);
Log.v(TAG, "accessibilityEnabled = " + accessibilityEnabled);
} catch (Settings.SettingNotFoundException e) {
Log.e(TAG, "Error finding setting, default accessibility to not found: "
+ e.getMessage());
}
TextUtils.SimpleStringSplitter mStringColonSplitter = new TextUtils.SimpleStringSplitter(':');
if (accessibilityEnabled == 1) {
Log.v(TAG, "***ACCESSIBILITY IS ENABLED*** -----------------");
String settingValue = Settings.Secure.getString(
mContext.getApplicationContext().getContentResolver(),
Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
if (settingValue != null) {
mStringColonSplitter.setString(settingValue);
while (mStringColonSplitter.hasNext()) {
String accessibilityService = mStringColonSplitter.next();
Log.v(TAG, "-------------- > accessibilityService :: " + accessibilityService + " " + service);
if (accessibilityService.equalsIgnoreCase(service)) {
Log.v(TAG, "We've found the correct setting - accessibility is switched on!");
return true;
}
}
}
} else {
Log.v(TAG, "***ACCESSIBILITY IS DISABLED***");
}
return false;
}
Source : https://stackoverflow.com/a/27642535/5182150
I have a boot receiver starting a service and also I can start and stop the service within the app.
But when I boot up the phone the service does start but stops instantly after starting. I have set the return on onStartCommand to START_STICKY.
This is my boot receiver:
public void onReceive(final Context context, final Intent intent) {
if(Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())){
Toast.makeText(context, "Boot received", Toast.LENGTH_LONG).show();
this.sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext());
this.mTelephonyMgr = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
this.encryption = new Encryption(mTelephonyMgr, sharedPreferences);
//startService(context);
Intent i = new Intent(context, ProfileActivity.class);
i.putExtra("boot_received", false);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
sharedPreferences.edit().putBoolean(Keys.AVAILABILITY, false).apply();
}
}
public void startService(final Context context){
final Intent intent = new Intent(context, PhoneCallService.class);
// If no token, try getting one.
if (Keys.phoneServiceToken == null || Keys.phoneServiceToken.isEmpty()) {
getToken(context, new Callbacks.ReceivePhoneServiceTokenCallback() {
#Override
public void receivePhoneServiceTokenCallback(boolean gotToken) {
if (gotToken) {
intent.putExtra(Keys.PHONE_SERVICE_TOKEN_EXTRA, Keys.phoneServiceToken);
intent.setAction(PhoneCallService.START_SERVICE);
context.startService(intent);
} else {
Log.d(LOG_TAG, String.valueOf(R.string.unexpected_error));
}
}
});
} else {
intent.putExtra(Keys.PHONE_SERVICE_TOKEN_EXTRA, Keys.phoneServiceToken);
intent.setAction(PhoneCallService.START_SERVICE);
context.startService(intent);
}
}
public void getToken(Context context, final Callbacks.ReceivePhoneServiceTokenCallback callback){
final String API = Keys.getpvmURL() + SharedResources.URL_DIRECT_CALL_TOKEN;
JsonObject json = encryption.getID();
json.addProperty("versionCode", BuildConfig.VERSION_CODE);
Ion.with(context)
.load(API)
.setTimeout(Keys.TIMEOUT_DIRECT_CALL_TOKEN)
.setJsonObjectBody(json)
.asJsonObject()
.withResponse()
.setCallback(new FutureCallback<Response<JsonObject>>() {
#Override
public void onCompleted(Exception e, Response<JsonObject> result) {
if(e == null) {
Log.d(LOG_TAG, "No Exceptions");
if(result.getHeaders().code() == 200) {
if(result.getResult().has("result")) {
Keys.phoneServiceToken = result.getResult().get("result").getAsString();
callback.receivePhoneServiceTokenCallback(true);
} else {
Log.w(LOG_TAG, "Does not have result");
callback.receivePhoneServiceTokenCallback(false);
}
} else {
Log.w(LOG_TAG, "Not getting 200 " + result.getHeaders().message());
callback.receivePhoneServiceTokenCallback(false);
}
} else {
Log.e(LOG_TAG, "Exception has occurred " + e.getClass());
callback.receivePhoneServiceTokenCallback(false);
}
}
});
This is my onStart and onCreate methods:
#Override
public void onCreate() {
Log.d(LOG_TAG, "Service started");
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(PhoneCallService.this);
notificationManager = (NotificationManager) PhoneCallService.this.getSystemService(Context.NOTIFICATION_SERVICE);
voiceBroadcastReceiver = new VoiceBroadcastReceiver();
registerReceiver();
audioManager = (AudioManager) PhoneCallService.this.getSystemService(Context.AUDIO_SERVICE);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(intent == null || intent.getAction() == null) {
Log.d(LOG_TAG, "No Action");
}
else if (intent.getAction().equals(START_SERVICE)) {
Log.d(LOG_TAG, "Starting PhoneCallService");
accessToken = intent.getStringExtra(Keys.PHONE_SERVICE_TOKEN_EXTRA);
Log.d(LOG_TAG, accessToken);
if (accessToken != null && !accessToken.isEmpty()) {
registerForCallInvites();
MyFcmListenerService.availableToCall = true;
} else {
stopSelf();
MyFcmListenerService.availableToCall = false;
}
}
else if (intent.getAction().equals(STOP_SERVICE)) {
stopSelf();
MyFcmListenerService.availableToCall = false;
}
else if (intent.getAction().equals(ACTION_INCOMING_CALL)) {
handleIncomingCallIntent(intent);
}
else {
Log.d(LOG_TAG, intent.getAction());
}
return START_STICKY;
}
For some reason I just can't get it to work on the boot request.
Sometimes when a user is sitting, or the phone is still on a table. the if statement which checks if inVehicle & 100% is triggered and the service in my app is started. I cannot figure out why ?
Activity Recognition in MainActivity
public String getDetectedActivity(int detectedActivityType) {
Resources resources = this.getResources();
switch (detectedActivityType) {
case DetectedActivity.IN_VEHICLE:
return resources.getString(R.string.in_vehicle);
case DetectedActivity.ON_BICYCLE:
return resources.getString(R.string.on_bicycle);
case DetectedActivity.ON_FOOT:
return resources.getString(R.string.on_foot);
case DetectedActivity.RUNNING:
return resources.getString(R.string.running);
case DetectedActivity.WALKING:
return resources.getString(R.string.walking);
case DetectedActivity.STILL:
return resources.getString(R.string.still);
case DetectedActivity.TILTING:
return resources.getString(R.string.tilting);
case DetectedActivity.UNKNOWN:
return resources.getString(R.string.unknown);
default:
return resources.getString(R.string.unidentifiable_activity, detectedActivityType);
}
}
public void requestActivityUpdates() {
if (!mGoogleApiClient.isConnected()) {
Toast.makeText(this, "GoogleApiClient not yet connected", Toast.LENGTH_SHORT).show();
} else {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
SharedPreferences.Editor editor = preferences.edit();
editor.putBoolean("acr", true);
editor.commit();
ActivityRecognition.ActivityRecognitionApi.requestActivityUpdates(mGoogleApiClient, 100, getActivityDetectionPendingIntent()).setResultCallback(this);
}
}
public void removeActivityUpdates() {
ActivityRecognition.ActivityRecognitionApi.removeActivityUpdates(mGoogleApiClient, getActivityDetectionPendingIntent()).setResultCallback(this);
}
private PendingIntent getActivityDetectionPendingIntent() {
Intent intent = new Intent(this, ActivitiesIntentService.class);
return PendingIntent.getService(this, 20, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
public void onResult(Status status) {
if (status.isSuccess()) {
Log.e(TAG, "Successfully added activity detection.");
} else {
Log.e(TAG, "Error: " + status.getStatusMessage());
}
}
public class ActivityDetectionBroadcastReceiver extends BroadcastReceiver {
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
#Override
public void onReceive(Context context, Intent intent) {
ArrayList<DetectedActivity> detectedActivities = intent.getParcelableArrayListExtra(Constants.STRING_EXTRA);
String activityString = "";
for (DetectedActivity activity : detectedActivities) {
activityString += "Activity: " + getDetectedActivity(activity.getType()) + ", Confidence: " + activity.getConfidence() + "%\n";
}
//mDetectedActivityTextView.setText(activityString);
//Toast.makeText(context, activityString, Toast.LENGTH_LONG).show();
Log.d(TAG2, activityString);
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
detectEnabled = preferences.getBoolean("mode", false);
buttonToggleDetect.setBackground(ui.uiToggle(getApplicationContext(), detectEnabled));
}
}
#Override
public void onConnected(Bundle bundle) {
Log.i(TAG, "Connected");
}
#Override
public void onConnectionSuspended(int i) {
Log.i(TAG, "Connection suspended");
mGoogleApiClient.connect();
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.i(TAG, "Connection failed. Error: " + connectionResult.getErrorCode());
}
Intent Service
public class ActivitiesIntentService extends IntentService {
// TODO REMOVE EXPORTED & ENABLED IN MANIFEST RELATED TO THIS CLASS
private static final String TAG = "ActivitiesIntentService";
public ActivitiesIntentService() {
super(TAG);
}
#Override
protected void onHandleIntent(Intent intent) {
boolean serviceState;
int inVehicle = 0;
int onFoot = 2;
int walking = 7;
int running = 8;
int tilting = 5;
int still = 3;
Intent serviceIntent = new Intent(this, CallDetectService.class); //creating a new intent to be sent to CallDetectService class
ActivityRecognitionResult result = ActivityRecognitionResult.extractResult(intent);
Intent i = new Intent(Constants.STRING_ACTION);
ArrayList<DetectedActivity> detectedActivities = (ArrayList) result.getProbableActivities();
// Log each activity.
Log.i(TAG, "activities detected");
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
serviceState = preferences.getBoolean("mode", false);
for (DetectedActivity da : detectedActivities) {
// // TODO: 16/07/16 local invehicle int precentage, if int is <50 return
// todo set up for logs from past day to be sent by user
if (da.getType() == inVehicle && da.getConfidence() >= 100 ) {
if (!serviceState) {
/*
ComponentName service = new ComponentName(getApplicationContext(), CallDetectService.class);
PackageManager pm = getApplicationContext().getPackageManager();
pm.setComponentEnabledSetting(service,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
*/
Log.d("Service", "service enabled by acr");
startService(serviceIntent);
MediaPlayer mp = MediaPlayer.create(getApplicationContext(), R.raw.music_marimba_chord);
mp.start();
//TODO ADD MP.FINISH HERE
}
}
//else if (da.getType() == still && da.getConfidence() >= 25)
else if (da.getType() == onFoot && da.getConfidence() >= 25
|| da.getType() == walking && da.getConfidence() >= 25
|| da.getType() == running && da.getConfidence() >= 25
|| da.getType() == still && da.getConfidence() == 100)
{
// stop detect service
if (serviceState) {
stopService(serviceIntent);
/*ComponentName service = new ComponentName(getApplicationContext(), CallDetectService.class);
PackageManager pm = getApplicationContext().getPackageManager();
pm.setComponentEnabledSetting(service,
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);
*/
Log.d("Service", "service disabled by acr");
}
}
}
i.putExtra(Constants.STRING_EXTRA, detectedActivities);
LocalBroadcastManager.getInstance(this).sendBroadcast(i);
}
}
Am I missing something? I really cant figure it out.
I tried putting in a component enabled/disabled setting in the intent service which is commented. when I had that in the code, the service did not start when the user was not inVehicle but when turn on and off when they actually where.
Any Help would be greatly appreciated.
I am using the default dictionary that comes with the pocketsphinx demo which is good for my purposes. When a user enters a phrase, the app starts a keyphrase listening but if the word is not found in the dictionary the app crashes. The app crashes onError() within a service. How is the error handling done? is there any way I can catch the error? Overall I would just like the service to call stopSelf() when an error happens so the main activity won't crash as well.
Errors:
ERROR: "kws_search.c", line 165: The word 'phonez' is missing in the dictionary
Fatal signal 11 (SIGSEGV) at 0x00000000 (code=1), thread 5389 (1994.wherephone)
Here is my service class:
public class WherePhoneService extends Service implements RecognitionListener {
private static String SettingStorage = "SavedData";
SharedPreferences settingData;
private SpeechRecognizer recognizer;
private String sInput;
private String sOutput;
private int seekVal;
private TextToSpeech reply;
private AsyncTask t;
public WherePhoneService() {
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
makeText(getApplicationContext(), "onHandle start", Toast.LENGTH_SHORT).show();
getValues();
startTTS();
t = new AsyncTask<Void, Void, Exception>() {
#Override
protected Exception doInBackground(Void... params) {
try {
Assets assets = new Assets(WherePhoneService.this);
File assetDir = assets.syncAssets();
setupRecognizer(assetDir);
} catch (IOException e) {
return e;
}
return null;
}
#Override
protected void onPostExecute(Exception result) {
if (result != null) {
//((TextView) findViewById(R.id.caption_text)).setText("Failed to init recognizer " + result);
} else {
switchSearch(sInput);
}
}
}.execute();
return Service.START_STICKY;
}
private void setupRecognizer(File assetsDir) throws IOException {
recognizer = defaultSetup()
.setAcousticModel(new File(assetsDir, "en-us-ptm"))
.setDictionary(new File(assetsDir, "cmudict-en-us.dict"))
// To disable logging of raw audio comment out this call (takes a lot of space on the device)
//.setRawLogDir(assetsDir)
// Threshold to tune for keyphrase to balance between false alarms and misses
.setKeywordThreshold(1e-45f)
// Use context-independent phonetic search, context-dependent is too slow for mobile
.setBoolean("-allphone_ci", true)
.getRecognizer();
recognizer.addListener(this);
// Create keyword-activation search.
recognizer.addKeyphraseSearch(sInput, sInput);
}
private void switchSearch(String searchName) {
recognizer.stop();
// If we are not spotting, start listening with timeout (10000 ms or 10 seconds).
if (searchName.equals(sInput))
recognizer.startListening(searchName);
else
recognizer.startListening(searchName, 10000);
}
#Override
public void onBeginningOfSpeech() {
}
#Override
public void onEndOfSpeech() {
if (!recognizer.getSearchName().equals(sInput))
switchSearch(sInput);
}
#Override
public void onPartialResult(Hypothesis hypothesis) {
if (hypothesis == null)
return;
String text = hypothesis.getHypstr();
makeText(getApplicationContext(), "Partial", Toast.LENGTH_SHORT).show();
if (text.equals(sInput)) {
setVolume();
// Text to speech
reply.speak(sOutput, TextToSpeech.QUEUE_ADD, null);
switchSearch(sInput);
}
else {
makeText(getApplicationContext(), "Try again", Toast.LENGTH_SHORT).show();
switchSearch(sInput);
}
}
#Override
public void onResult(Hypothesis hypothesis) {
if (hypothesis != null) {
// restart listener and affirm that partial has past
makeText(getApplicationContext(), "end", Toast.LENGTH_SHORT).show();
//recognizer.startListening(sInput);
switchSearch(sInput);
}
}
public void onError(Exception e) {
e.printStackTrace(); // not all Android versions will print the stack trace automatically
Intent intent = new Intent ();
intent.setAction ("com.mydomain.SEND_LOG"); // see step 5.
intent.setFlags (Intent.FLAG_ACTIVITY_NEW_TASK); // required when starting from Application
startActivity (intent);
stopSelf();
}
#Override
public void onTimeout() {
switchSearch(sInput);
}
public void startTTS() {
reply = new TextToSpeech(getApplicationContext(), new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
if(status != TextToSpeech.ERROR){
reply.setLanguage(Locale.UK);
}
}
});
}
public void getValues() {
settingData = getBaseContext().getSharedPreferences(SettingStorage, 0);
sInput = settingData.getString("inputstring", "Where is my phone").toString().toLowerCase().replaceAll("[^\\w\\s]", "");
sOutput = settingData.getString("outputstring", "").toString().toLowerCase();
seekVal = settingData.getInt("seekval", 0);
}
public void setVolume() {
int seekValConvert = 0;
AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
int getMaxPhoneVol = audioManager.getStreamMaxVolume(audioManager.STREAM_MUSIC);
seekValConvert = ((seekVal * getMaxPhoneVol)/100);
audioManager.setStreamVolume(audioManager.STREAM_MUSIC, seekValConvert, 0);
}
#Override
public void onDestroy() {
super.onDestroy();
makeText(getApplicationContext(), "destroy", Toast.LENGTH_SHORT).show();
recognizer.cancel();
recognizer.shutdown();
t.cancel(true);
}
}
Crash is a bug in pocketsphinx-android. If you update to latest version from github, it should properly throw RuntimeException on any errors in methods addKeyphrase and setSearch.
in the following coding i am getting battery level of some percentage.but i want to call notify characteristics so that for every 5 to 10 secs it updates the percentage of battery.so please help me.the following is my device control activity,in this i coded as follows.
private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) {
displayData(intent.getStringExtra(BluetoothLeService.EXTRA_DATA));
}
}
};
and in the following method i am setting battery value and displaying in the value in percentage on image.
private void displayData(String data) {
Log.v("______________________No serives_______________",data );
if (data != null) {
mBluetoothLeService.setCharacteristicNotification(mNotifyCharacteristic, true);
battery.setText(data);
int x=Integer.parseInt(battery.getText().toString());
image_level.getLayoutParams().height = x*2;
}
else if (data==null)
battery.setText(data);
}
and the following is my ble service in this i add the set notification method wh
ich is as follows.
public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic,
boolean enabled) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
//For cube write
if (UUID_BatteryService.equals(characteristic.getUuid())) {
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
UUID.fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mBluetoothGatt.writeDescriptor(descriptor);
}
}
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
};
public boolean writeCharacteristic(BluetoothGattCharacteristic i){
//check mBluetoothGatt is available
if (mBluetoothGatt == null) {
Log.e(TAG, "lost connection");
return false;
}
BluetoothGattService Service = mBluetoothGatt.getService(UUID_BatteryService);
if (Service == null) {
Log.e(TAG, "service not found!");
//////////NO service found...........
return false;
}
boolean status = mBluetoothGatt.writeCharacteristic(i);
Log.e(TAG, "bluetooth write status"+status);
return status;
}
private void broadcastUpdate(final String action) {
final Intent intent = new Intent(action);
sendBroadcast(intent);
}
private void broadcastUpdate(final String action,
final BluetoothGattCharacteristic characteristic) {
final Intent intent = new Intent(action);
if(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG_BATTERY.
toString().
equalsIgnoreCase(characteristic.getUuid().toString())) {
Log.v("_____________","in broadcastupdate..........");
final byte[] data = characteristic.getValue();
if (data != null && data.length > 0) {
final StringBuilder stringBuilder = new StringBuilder(data.length);
for(byte byteChar : data)
stringBuilder.append(String.format("%02X ", byteChar));
final int flag = characteristic.getProperties();
int format = -1;
if ((flag & 0x01) != 0) {
format = BluetoothGattCharacteristic.FORMAT_UINT16;
Log.d(TAG, " format UINT16.");
} else {
format = BluetoothGattCharacteristic.FORMAT_UINT8;
Log.d(TAG, " UINT8.");
}
int batterylevel = characteristic.getIntValue(format, 0);
intent.putExtra(EXTRA_DATA, String.valueOf(batterylevel));
//intent.putExtra(EXTRA_DATA,new String(data));
}
}
sendBroadcast(intent);
}
If I well understood your question, you will need a Timer in order to check you battery level regularly.
For instance, you could use this code after starting your device control activity, maybe at the end of the onServiceConnected method :
please put the timer at the end of onServiceConnected() method of mServiceConnection object
Timer timer = new Timer("batteryTimer");
TimerTask task = new TimerTask() {
#Override
public void run() {
mBluetoothLeService.getBattery();
}
};
timer.scheduleAtFixedRate(task, 0, 5000);
And do not forget to call timer.cancel() when the activity is finishing.
And in the service, you could put something like that :
public void getBattery() {
if (mBluetoothGatt == null) {
Log.e(TAG, "lost connection");
}
BluetoothGattService batteryService = mBluetoothGatt.getService(Battery_Service_UUID);
if(batteryService == null) {
Log.d(TAG, "Battery service not found!");
return;
}
BluetoothGattCharacteristic batteryLevel = batteryService.getCharacteristic(Battery_Level_UUID);
if(batteryLevel == null) {
Log.d(TAG, "Battery level not found!");
return;
}
mBluetoothGatt.readCharacteristic(batteryLevel);
}
It is an example which would need to be modified but that gives you an idea on how to do it.
Somebody already did access to the battery value in the link below :
How to get the battery level after connect to the BLE device?