So I have a bit of a problem. I am trying to make my app do things based on the message it receives through GCM. In this case it's supposed to make a sound by using the TextToSpeech class. It kind of works, but not the first time I send the message. I realise this is probably because TextToSpeech hasn't been instantiated, but I'm not sure how go to about and do that? I tried onInit(), but that didn't work at all.
Also, what is the best way to shut down TTS in my example?
Disclaimer: I come from a PHP background, and know very little Java. I try to learn by doing, so please forgive me if this is a silly question. Thanks in advance!
public class GCMIntentService extends GCMBaseIntentService {
private static final String TAG = "GCMIntentService";
public static TextToSpeech mtts;
public GCMIntentService() {
super(SENDER_ID);
}
#Override
protected void onMessage(Context context, Intent intent) {
Log.i(TAG, "Received message");
String message = intent.getExtras().getString("message");
mtts = new TextToSpeech(context, null);
if (message.startsWith("makeSound")) {
mtts = new TextToSpeech(context, null);
mtts.setLanguage(Locale.US);
mtts.speak(message, TextToSpeech.QUEUE_FLUSH, null);
}
}
}
It doesn't work the first time because the initialization of TextToSpeech is asynchronous. You can not simple instantiate it and use it as you are doing. You should provide a callback to be called once the TextToSpeech has been initialized if you want to use it right away.
mTextToSpeech = new TextToSpeech( this, new TextToSpeech.OnInitListener()
{
#Override
public void onInit( int status )
{
// Check for status might not be initialized due to errors
// Configure language/speed
}
} );
It does work the rest of the times, because mtts is static. This means that is a class variable and is not destroyed/initialized when creating new instances of the service. By the second time you use this service, this variable was already initialized in the first service execution.
Related
Now that the PROVIDERS_CHANGED intent-filter can't be set in the Manifest, I'm doing it dynamically.
However, I need to register/unregister the dynamically coded Receiver in multiple places.
Due to this, I am creating a "Helper" Class that contains a static method with the Receiver code.
MY ISSUE: I can't seem to figure out how to get the Context in order to register/unregister receiver.
Here is my current code:
public class GpsReceiverHelper {
public static void gpsReceiverCode() {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("android.location.PROVIDERS_CHANGED");
final BroadcastReceiver gpsReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction() != null &&
intent.getAction().matches("android.location.PROVIDERS_CHANGED")) {
// RECEIVER CODE HERE
}
}
};
this.registerReceiver(gpsReceiver, intentFilter);
// THIS IS WHERE I CAN'T GET A CONTEXT (USING "this" OR OTHERWISE)
}
}
MY QUESTIONS:
(A) - How can I go about retrieving a context here?
(B) - Is creating a helper class with a public static method the right way to be doing this?
How can I go about retrieving a context here?
Pass it in as a parameter (public static void gpsReceiverCode(Context context)).
I need to register/unregister the dynamically coded Receiver in multiple places
When your receiver was in the manifest, it was "registered" in one place. Hence, when you do it dynamically, you can register it in one place (e.g., custom Application subclass).
Is creating a helper class with a public static method the right way to be doing this?
Probably not, insofar as you probably should not be needing to use this code in 2+ places.
I am using the quickstart-android code provided by google but after many attempts I cam unable to find a context that is not returning null. The BarcodeScannerProcessor is not itself an Activity, so I have attempted to create an instance of the LivePreviewActivity and use that as the context in the intent, but it's null.
The goal is to once a valid barcode is recognized I want to open a new activity that allows a user to verify value and on the push of a button call a webservice to post the barcode to a database via API. I am having a hard time finding a valid context and the app is crashing when it trys to execute the Intent.
Starting at line 97-107:
https://github.com/jamiekeefer/quickstart-android/blob/master/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/barcodescanning/BarcodeScanningProcessor.java
for (int i = 0; i < barcodes.size(); ++i) {
FirebaseVisionBarcode barcode = barcodes.get(i);
BarcodeGraphic barcodeGraphic = new BarcodeGraphic(graphicOverlay, barcode);
graphicOverlay.add(barcodeGraphic);
System.out.println(barcode.getRawValue());
if (!barcode.getRawValue().equals("") ) {
System.out.println("Got the number:" + barcode.getRawValue() + " Context: " + mContext); //OLD SCHOOL DEBUG OUTPUT
//enter code to start activity
Intent intent = new Intent(mContext, SendScannedBarcode.class);
String message = scannedBarcode;
intent.putExtra(EXTRA_MESSAGE, message);
mContext.startActivity(intent);
}
}
You can back up in the repo to see the instance of the LivePreviewActivity where I trying to get context.
I have tried a number of things and read about Context, Views and Activities and basically have completely confused myself. The only tuts I can find are using Kotlin, which is not helping clarify things.
I appreacite any help in indentifying or contruting a valid Intent from this Context. Thank you.
So I am assuming that in your LivePreviewActivity you are creating an object of the class BarcodeScanningProcessor. What you can do is change the constructor in the BarcodeScanningProcessor class to accept a context and then you pass in your LivePreviewActivity's context.
This is what the code should look like:
In BarcodeScanningProcessor:
public BarcodeScanningProcessor(Context context) {
// Note that if you know which format of barcode your app is dealing with, detection will be
// faster to specify the supported barcode formats one by one, e.g.
// new FirebaseVisionBarcodeDetectorOptions.Builder()
// .setBarcodeFormats(FirebaseVisionBarcode.FORMAT_QR_CODE)
// .build();
detector = FirebaseVision.getInstance().getVisionBarcodeDetector();
this.mContext = context;
}
Then in LivePreviewActivity:
In the particular case of your activity you would do:
case BARCODE_DETECTION:
Log.i(TAG, "Using Barcode Detector Processor");
cameraSource.setMachineLearningFrameProcessor(new BarcodeScanningProcessor(getApplicationContext()));
break;
Or if you just wanted to create an object of the class you could do:
BarcodeScanningProcessor bsp = new BarcodeScanningProcessor(getApplicationContext());
This should now give your BarcodeScanningProcessor class the context of your activity. Now, in BarcodeScanningProcessor, mContext should not be null and will have the context of your activity. I hope this answers your question.
try this create Application class
import android.app.Application;
public class MyApplication extends Application {
static MyApplication instance;
#Override
public void onCreate() {
super.onCreate();
instance=this;
}
public static MyApplication getInstance() {
return instance;
}
}
Register in manifest file
<application
..
android:name="com.yourpackage.MyApplication"
..>
.
.
.
</application>
start activity using this MyApplication.
Intent intent = new Intent(MyApplication.getInstance(), SendScannedBarcode.class);
String message = scannedBarcode;
intent.putExtra(EXTRA_MESSAGE, message);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MyApplication. getInstance().startActivity(intent);
Another way of handling the issue is create new constructor of BarcodeScanningProcessor which takes interface call back and once processing is done pass back result to caller.
public interface BarcodeUpdateListener {
#UiThread
void onBarcodeDetected(Barcode barcode);
}
private BarcodeUpdateListener callback;
public BarcodeScanningProcessor(BarcodeUpdateListener callback){
this.callback = callback;
detector = FirebaseVision.getInstance().getVisionBarcodeDetector();
}
Once you get the result pass result to caller
callback.onBarcodeDetected(<Barcode>)
You can get the context from graphicOverlay:
Context context = graphicOverlay.getContext();
lately i have been researching about memory leaks in java/android and pretty much everywhere it says that instead of anonymous classes i should use static inner classes with weak references.
so, in my android app i started doing that but very quickly got tired of it because it's a lot of boilerplate code... i think have an alternative solution which i would prefer to use, but i'm juts not sure that it is a valid alternative to static inner classes in terms of preventing memory leaks. as i said before, i haven't seen this solution suggested anywhere else (all say to use static inner classes) so thats why im not sure my alternative will work.
ill use a simple example from my app:
i have a class called WebClient which handles asynchronous web requests and it accepts an interface called iCallback which returns the response from the server to the caller, and in my activity once i get this callback i need to dismiss a dialog, and maybe perform some activity related things (like trigger onBackPressed() and setResult()).
so here is my static inner class i have created:
private static class CallBack implements WebClient.ICallback
{
private WeakReference<ProgressDialog> mProgDiag;
private WeakReference<BaseActivity> mActivity;
public CallBack(BaseActivity activity, ProgressDialog progDiag)
{
this.mProgDiag = new WeakReference<>(progDiag);
this.mActivity = new WeakReference<>(activity);
}
#Override
public void onCallback(String data)
{
String responseAsString = Utils.extractStringFromResponse(...);
final BaseActivity parentActivity = mActivity.get();
ProgressDialog dialog = mProgDiag.get();
if(dialog != null)
{
dialog.dismiss();
}
if (responseAsString == null)
{
if(parentActivity != null)
{
Utils.makeServerErrorDialog(parentActivity,
new iDialogButtonClickedListener()
{
#Override
public void onDialogButtonClicked()
{
parentActivity.onBackPressed();
}
});
}
return;
}
//everything is ok
if (responseAsString.equals("1"))
{
if(parentActivity != null)
{
Intent result = new Intent();
result.putExtra(...);
parentActivity.setResult(Activity.RESULT_OK, result);
}
}
else
{
Utils.reportErrorToServer(...);
if(parentActivity != null)
{
parentActivity.setResult(Activity.RESULT_CANCELED);
}
}
if(parentActivity != null)
{
parentActivity.onBackPressed();
}
}
}
so for every variable i need in this static inner class i have to create a new weak reference, then retrieve the object itself, and then every time i want to access it i need to check whether it's null... that seems like a lot of code to me.
and here is my suggested alternative:
public abstract class BaseActivity extends AppCompatActivity
implements WebClient.ICallback
{
private static final String TAG = "BaseActivity";
WebClient.ICallback mCallBack;
ProgressDialog mProgDiag;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(...);
mCallBack = this;
//some code to invoke a server request on button click
//and passing mCallBack to the request
}
#Override
public void onCallback(String data)
{
String responseAsString = Utils.extractStringFromResponse(...);
mProgDiag.dismiss();
if (responseAsString == null)
{
Utils.makeServerErrorDialog(this,
new iDialogButtonClickedListener()
{
#Override
public void onDialogButtonClicked()
{
onBackPressed();
}
});
return;
}
//everything is ok
if (responseAsString.equals("1"))
{
Intent result = new Intent();
result.putExtra(...);
setResult(Activity.RESULT_OK, result);
}
else
{
Utils.reportErrorToServer(...);
setResult(Activity.RESULT_CANCELED);
}
onBackPressed();
}
#Override
protected void onPause()
{
mCallBack = null;
super.onPause();
}
#Override
protected void onResume()
{
super.onResume();
mCallBack = this;
}
}
to me this seems much cleaner: no creating and retrieving instances of weak references for every variable i need access to, i can directly invoke activity methods (e.g. onBackPressed()), and no checking for null everywhere.
the only place i would now have to check for null is inside WebClient class before invoking the callBack method.
so my question is, does this approach achieve the same result in terms of preventing memory leaks? is it a "worthy" alternative to static inner classes?
Unfortunately, your approach does not work. By implementing the WebClient.ICallback in your activity, rather than an inner class, you don't get rid of the leak. The leak happens not because the references to activity and dialog are implicit in an anonymous class, or in lambda, or in a non-static inner class instance; the happens when the WebClient keeps this reference while the activity is gone (it is not destroyed, because there is a strong reference to it).
The special mCallBack that you set to null when the activity is paused, gains nothing. Just as well, you can simply pass your activity instance to the WebClient. Now there is a strong reference to your activity, which is managed by someone (async handlers of the WebClient), who is not under your control. If you are unlucky, the async handler will get stuck somewhere and will never release this reference.
Please read this detailed explanation.
Note that WebView itself can cause a memory leak, if special measures are not undertaken!
I want to create a separate class within my application to handle error reporting and send specific errors to a database. However, I'm unable to figure out what the Context should be and how this should be properly coded. I assume it should still be possible, I just need to code it differently, if that is not the case, what is the best solution for me?
public class SendError implements Runnable
{
private String url;
public SendError(String errors, String form, String database, String SQL)
{
url = string;
Handler handler = new Handler();
handler.post(new Runnable() {
public void run() {
Toast toast = Toast.makeText(getContext, msg, Toast.LENGTH_LONG);
toast.show();
}
});
}
}
EDIT:
What I'm trying to do is create one class for my entire application that handles recording of SQL errors when submitting data to the database. The class needs to do 2 simple things. Submit information based on what form, database, time submitted, and the SQL code that created the error. The other thing I would like this class to do is to display a toast giving basic error information back to the user. I have the data submission portion of this worked out properly (hence the reason for the Runnable), but am still getting errors for the Toast.
Shouldn't do the work in your constructor, this makes your separate class useless.
public class SendError implements Runnable
{
private final Context context;
private final String url;
public SendError(Context context, String string) {
this.context = context;
this.url = string;
}
public void makeToast(String msg, String errors, String form, String database, String SQL) {
Handler handler = new Handler();
handler.post(new Runnable() {
public void run() {
Toast toast = Toast.makeText(context, msg, Toast.LENGTH_LONG);
toast.show();
}
});
}
}
Your context needs to be the relevant context, from using a Toast the Context is usually an Activity which can take the form of:
this (in an Activity)
ActivityName.this (in a inner class of an Activity)
getActivity (in a Fragment inside an Activity)
For example:
new SendError(YourActivity.this, "something").makeToast("Hello", "errors", "form", "database", "sql");
Just need to pass Context in the constructor when you create this class.
I would advise you rethink this class though - it's called "SendError" which sounds like a method name, it implements Runnable for some reason, and it's notifying the user with Toasts - sounds like too much for one class.
Toast toast = Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_LONG).show();
or
Toast toast = Toast.makeText(SendError.this, msg, Toast.LENGTH_LONG).show();
This is my first post and I did not find anything similar, so I've decided to ask.
Im developing a Poker Game for Android to practice the SDK and refresh/improve my Java. Its a simple app that control a texas hold'em poker hand.
Initally, I wrote my classes using only Java SE and it looks fine. Each class has its own purpose and testing it with console input/output, I can see it really works :)
Last week, I decided to port it to Android to see things happening through a graphic interface, so I got the resource images, make an Activity and included my poker package.
Before port to Android I can just put a println (or readLine) to see whats going on and send my inputs. Now Im stuck in how each class can communicate to the game activity to provide what must be drawn. If possible, I don't want insert Android draw code inside game classes. Im trying find a way to exchange messages between my Activity and the game classes and Id like some suggetions. Im new in developing Android apps, so I dont know all mechanics to do this.
Below are the snippet from my activity:
package my.poker.game;
//import stuff
public class ActivityHand extends Activity
{
private static Vector<Player> Players = new Vector<Player>();
public static final int MAX_PLAYERS = 8;
public static void startEmptyTable()
{
Players.removeAllElements();
Players.setSize(MAX_PLAYERS);
}
public static void LeaveTable(int pos)
{
Players.set(pos, null);
}
public static void SitTable(int pos, Player player)
{
Players.set(pos, player);
}
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
int cash = 1000;
startEmptyTable();
SitTable(0, new Jogador("William", cash));
SitTable(2, new Jogador("Richard", cash));
SitTable(4, new Jogador("John", cash));
SitTable(6, new Jogador("Paul", cash));
SitTable(8, new Jogador("Albert", cash));
//Start a Hand.... in future this will be a loop for each Hand
Hand hand = new Hand(Players);
}
}
The object hand, will select a Dealer, deal the cards, control the small and big blinds and start the game loop.
The question is: how the hand class can tell the Activity to Draw and pass an object containing what to draw?
Thanks a lot for your help
Editing: I've decided to try implementing it using a Handler and passing simple messages. As I read from Handler at Developers a Handler object is assigned to thread's MessageQueue, so I tried to put this into my Activity Class (before Hand hand = new Hand (...) ):
Handler handler = new Handler()
{
#Override
public void handleMessage(Message msg)
{
Bundle bundle = msg.getData();
// Do something with message contents
}
};
And inside the Hand class I put this when I want to draw something:
Handler handler = new Handler();
Message msg = new Message();
Bundle bundle = new Bundle();
bundle.putString("Key", "The Key's Value");
msg.setData(bundle);
handler.sendMessage(msg);
As I understood, both handlers are from same thread, so they are assigned to same MessageQueue right? I tought when I send a message inside Hand class, the Activity class can receive it in handleMessage method and processes any message I send, but handleMessage doesn't execute.
What am I missing?
Thanks again
To call methods in the activity, you want to pass the activity to this class.
for example:
public class PokerActivity extends Activity
{
#Override
public void onCreate(Bundle savedInstanceState)
{
Hand hand = new Hand(this);
}
public void setVisibleHand(Player player)
{
<do something in the activity>
}
}
public class Hand
{
PokerActivity pokerActivity;
public Hand(PokerActivity activity)
{
this.pokerActivity = activity;
}
public void setVisibleHand()
{
pokerActivity.setVisibleHand(player1);
}
}
Now, this might not be the best way to do it. In Android you have to be carefull to not leak the context, or you might be getting trouble with the memory. (simply passing the activity/context might be the easy way, but is also the easiest way to leak the context.)
I'd advise you to look at some simple tutorials first, to get a feeling of how android activities work.
You could use a Handler and Message system to communicate between your classes.
This tutorial by Lars Vogel should help you Android Threads, Handlers and AsyncTask - Tutorial
You will have to create another class to make the interactions with your own classes and the activity itself.
From that class you can use the activity context to control the android activity.
The approach about using Handlers and Messages is good but would require you to modify your game classes.
Maybe you should extend View Class to draw the Hand.
http://developer.android.com/reference/android/view/View.html