I have an activity (MainActivity) that implements TextToSpeech and works perfectly. When a button's onClick is called, it speaks whatever is typed in EditText.
MainActivity:
public class MainActivity extends AppCompatActivity implements TextToSpeech.OnInitListener{
private TextToSpeech engine;
private EditText text;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text = (EditText) findViewById(R.id.text);
engine = new TextToSpeech(this, this);
Intent i=getIntent();
Bundle b=i.getExtras();
word=b.getString("word");
speakText2(word);
}
// speakText is called by onClick button
public void speakText(View v) {
String textContents = text.getText().toString();
engine.speak(textContents, TextToSpeech.QUEUE_FLUSH, null, null);
}
public void speakText2(String textContents) {
engine.speak(textContents, TextToSpeech.QUEUE_ADD, null, null);
}
#Override
public void onInit(int i) {
if (i == TextToSpeech.SUCCESS) {
//Setting speech Language
engine.setLanguage(Locale.ENGLISH);
engine.setPitch(1);
}
}
}
Now, I want to call MainActivity from another activity and pass a string to speak up.
I tried:
MainActivity mainactivity = new MainActivity();
String word;
word = "speak";
mainactivity.speakText2(word); // Error
But, getting error:
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'int android.speech.tts.TextToSpeech.speak(java.lang.CharSequence, int, android.os.Bundle, java.lang.String)' on a null object reference
at MainActivity.speakText2(TTSEngine.java:53)
I tried using intent from another activity:
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("word", word);
startActivity(intent);
But, getting error:
I/TextToSpeech: Sucessfully bound to com.google.android.tts
W/TextToSpeech: speak failed: not bound to TTS engine
W/TextToSpeech: speak failed: not bound to TTS engine
W/TextToSpeech: speak failed: not bound to TTS engine
I/TextToSpeech: Connected to ComponentInfo{com.google.android.tts/com.google.android.tts.service.GoogleTTSService}
I/TextToSpeech: Set up connection to ComponentInfo{com.google.android.tts/com.google.android.tts.service.GoogleTTSService}
I tried to implement TextToSpeech in the activity I want to use it in. But, it does not work for the first time I call speakText2 and give error:
W/TextToSpeech: speak failed: not bound to TTS engine
I/TextToSpeech: Connected to ComponentInfo{com.google.android.tts/com.google.android.tts.service.GoogleTTSService}
I/TextToSpeech: Set up connection to ComponentInfo{com.google.android.tts/com.google.android.tts.service.GoogleTTSService}
For rest of the time it work perfectly. Any idea how to fix this?
You can only let the engine speak, after onInit is done, so do following in onInit():
if (status == TextToSpeech.SUCCESS) {
speakText2(word);
}
You have to use an Intent to start an Activity. See https://developer.android.com/training/basics/firstapp/starting-activity.html
When you create your Activity instance manually the onCreate method is not called (and any other lifecycle methods) - that’s why you’re getting an NPE accessing your engine property - it wasn’t initialized.
Related
I am having trouble with LoaderCallbacks in my project. I have implements LoaderManager in android studio. I am trying to restart the loader whenever search button is press by user.
public class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<List<Book>>
mSearchButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Check connection status
checkConnection(cm);
if (isConnected) {
updateQueryUrl(mSearchViewField.getQuery().toString());
restartLoader();
Log.i(LOG_TAG, "Search value: " + mSearchViewField.getQuery().toString());
}else{
// Clear the adapter of previous book data
mAdapter.clear();
// Set mEmptyStateTextView visible
mEmptyStateTextView.setVisibility(View.VISIBLE);
// ...and display message: "No internet connection."
mEmptyStateTextView.setText("No Internet Connection");
}
}
});
But, under restartLoader(), when I try to call getLoaderManager() to restart the loader, it's saying that callback argument is wrong, 3rd argument type. I am not sure what should i use for the callback.
public void restartLoader() {
mEmptyStateTextView.setVisibility(GONE);
progressBar.setVisibility(View.VISIBLE);
getLoaderManager().restartLoader(BOOK_LOADER_ID,null, MainActivity.this);
}
getLoaderManager is deprecated and uses the deprecated framework Loaders.
You should use LoaderManager.getInstance(MainActivity.this) instead, which uses the correct Support Library/AndroidX Loaders, which is probably the LoaderManager.LoaderCallbacks you've imported.
LoaderManager.getInstance(MainActivity.this)
.restartLoader(BOOK_LOADER_ID, null, MainActivity.this);
i have this AccessibilityService class for the USSD
public class USSDService extends AccessibilityService {
public static String TAG = "USSDService";
#Override
public void onAccessibilityEvent(AccessibilityEvent event) {
Log.d(TAG, "onAccessibilityEvent");
String text = event.getText().toString();
if (event.getClassName().equals("android.app.AlertDialog")) {
performGlobalAction(GLOBAL_ACTION_BACK);
Log.d(TAG, text);
Intent intent = new Intent("com.times.ussd.action.REFRESH");
intent.putExtra("message", text);//this is the value that i want to return to MainActivity
Toast.makeText (this,text,Toast.LENGTH_LONG).show();
}
}
#Override
public void onInterrupt() {
}
#Override
protected void onServiceConnected() {
super.onServiceConnected();
Log.d(TAG, "onServiceConnected");
AccessibilityServiceInfo info = new AccessibilityServiceInfo();
info.flags = AccessibilityServiceInfo.DEFAULT;
info.packageNames = new String[]{"com.android.phone"};
info.eventTypes = AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
info.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;
setServiceInfo(info);
}}
and i invoke in main activity like this
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
////////////////USSD////////////////////
Intent mIntent = new Intent(this, USSDService.class);
startService(mIntent);
}
and this is a function that dial ussd
private void dailNumber(String code) {
String ussdCode = "*" + code + Uri.encode("#");
Intent callIntent = new Intent(Intent.ACTION_CALL)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
callIntent.setData(Uri.parse("tel:" + ussdCode));
callIntent.putExtra("simSlot", 0);
startActivity(callIntent);
}
when i call this function by clicking a button, every thing is ok and the response of ussd call show in Toast as i code it in function onAccessibilityEvent
what i want is return the response value to MainActivity
Accessibility services cannot be started in the manner you are attempting to start them. They can only be managed from the Accessibility Settings menu. This is for good reason. Accessibility services can read screen contents. OH, you downloaded my app, that's nice. NOW I'm going to launch an Accessibility Service that watches all of your screen content for things that look like Credit Card numbers.
Intent mIntent = new Intent(this, USSDService.class);
startService(mIntent);
The lines of code above ARE NOT accomplishing what you think they are. The accessibility service will launch (call your service's onCreate), but it will launch in a functionally limited state that does not allow it to bind to applications and the Android Operating System in the way an Accessibility Service normally would.
Once properly configured, go to Settings -> Accessibility and find your service listed next to TalkBack. Then turn it on. Once you do this, in order to communicate between your two processes you're going to need some type of interprocess communication mechanism. For simple communication you can consider using SharePreferences. Otherwise, you're probably going to have to look into BroadCastReceivers.
See how far that gets you, and ask another question if you need!
In Android sometimes when we use an app and we receive a call , appears the full screen Incoming call activity
Instead if i create a new blank main activity and i put a simple BroadCast receiver, when im in the main activity and i receive a call this compares:
There is a way to show the full screen incoming call or just hide the incoming call popup notification ?
I searched a lot but i have not found anything...
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public static class PhoneStateReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "OK", Toast.LENGTH_LONG).show();
}
}
}
in android The system UI may choose to display a heads-up notification, instead of launching your full-screen intent, while the user is using the device. check it out Display time-sensitive notifications
I am working on an SMS application and I have a method in my MainActivity to perform a button click:
public void updateMessage() {
ViewMessages.performClick();
}
This method works fine and performs the button click when I call this method from inside the MainActivity class.
But, when I call this method from any other class as shown below, where I call the Main Activity's updateMessage method from the IntentServiceHandler class, I am getting a NullPointerException:
java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.widget.Button.performClick()' on a null object reference
public class IntentServiceHandler extends IntentService {
public IntentServiceHandler() {
super("IntentServiceHandler");
}
#Override
protected void onHandleIntent(Intent intent) {
String message = intent.getStringExtra("message");
TransactionDataBase transactionDB = new TransactionDataBase(this, 1);
transactionDB.addMessage(message);
MainActivity mainActivity = new MainActivity();
mainActivity.updateMessage();
}
}
How can I handle this?
Edit: I even tried to make the updateMessage method static, and now i get the following exception
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
Don't call the method of Activity in an IntentService, try to use Intent to communicate between Activity and IntentService.
Replace the last two statements onHandleIntent() with
Intent intent = new Intent();
broadcastIntent.setAction(MainActivity.UPDATE_MESSAGE);
broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT);
sendBroadcast(intent);
And you should register a BroadcastReceiver in onCreate() of MainAcitivty like
private BroadcastReceiver receiver;
#Override
public void onCreate(Bundle savedInstanceState){
// ....
IntentFilter filter = new IntentFilter();
filter.addAction(UPDATE_MESSAGE);
receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// do something based on the intent's action
// for example, call updateMessage()
}
};
registerReceiver(receiver, filter);
}
onHandleIntent of IntentService run in another thread (instead of main thread / ui thread), so Updating UI components in onHandleIntent isn't permitted.
I have a service that is, among other things, downloading images from internet. When this is done I want to show this image in a custom Activity that has a dialog theme. But I only want to use this pop up if the app is running, otherwise I just want to create a notification.
But I get an exception when I try to start an activity from my service and i feel that maybe this isn't the right way to do it?
It says:
android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
So my question is if this is the right way to do this by setting that flag or how should I get my downloaded image from my service to an activity. Can I in some way tell an activity to start a new activity from my service class?
I think using Broadcast Receiver is better option for you.
Add Below Method in Service and call this method when image Download Complete.
private void updateMyActivity(Context context) {
if(MainActivity.activityStatusFlag){
//update the activity if activityStatusFlag=true;
Intent intent = new Intent("mUpdateActivity");
context.sendBroadcast(intent);
}else{
//display notification if activityStatusFlag=false;
}
}
In Activity Add Following Code.
public class MainActivity extends Activity{
public static boolean activityStatusFlag= false;
//define this variable to check if activity is running or not.
#Override
protected void onResume() {
super.onResume();
activityStatusFlag = true;
this.getApplicationContext().
registerReceiver(mMessageReceiver,new IntentFilter("mUpdateActivity"));
}
#Override
protected void onPause() {
super.onPause();
activityStatusFlag = false;
this.getApplicationContext().unregisterReceiver(mMessageReceiver);
}
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//Display Popup or update Activity
}
};
}