Android Handler leaking - java

In my android application, I am sending messages to contacts.. and it is showing " This handler class should be static or else might be leak". My application is crashing in Mobile phone but it is working in Emulator, I am giving the code below pls go through it and any error if anybody can help please help..
progresshandler = new Handler()
{
public void handleMessage(Message msg)
{
//progressDialog.dismiss();
//Toast.makeText(SendMessagesActivity.this, "Messages Sent",Toast.LENGTH_LONG).show();
new ProgressTask().execute();
}
};

To avoid leaking Handler create Custom class that extends Handler class as below :
// Handler of incoming messages from clients.
private static class IncomingHandler extends Handler {
private WeakReference<YourActivity> yourActivityWeakReference;
public IncomingHandler(YourActivity yourActivity) {
yourActivityWeakReference = new WeakReference<>(yourActivity);
}
#Override
public void handleMessage(Message message) {
if (yourActivityWeakReference != null) {
YourActivity yourActivity = yourActivityWeakReference.get();
Edited : new ProgressTask().execute();
// switch (message.what) {
// }
}
}
}
Create object of this class wherever you want to use as below.
private IncomingHandler mPulseHandler;
mPulseHandler = new IncomingHandler(HomeActivity.this);
mPulseHandler.sendEmptyMessage(0);
Edited :
IncomingHandler progresshandler = new IncomingHandler(YourActivity.this);
if (editMessage.getText().toString().length() > 0) {
SendMessagesThread thread = new SendMessagesThread(progresshandler);
thread.start();
// progressDialog.show();
}
Edited :
Declare this task in your activity :
private ProgressTask progressTask;
Create instance of it in onCreate()
progressTask=new ProgressTask();
Change line in IncomingHandler :
yourActivity.progressTask.execute();
Thanks

Related

FirebaseInAppMessagingClickListener not Calling android

I am using FirebaseInAppMessaging and it's works. Then i register action call back using FirebaseInAppMessagingClickListener, it's not calling.
public class InAppMessageClick implements FirebaseInAppMessagingClickListener, FirebaseInAppMessagingImpressionListener, FirebaseInAppMessagingDisplay {
String TAG = "InAppMessageClick";
#Override
public void messageClicked(InAppMessage inAppMessage, Action action) {
// Determine which URL the user clicked
String url = action.getActionUrl();
LogUtils.i(TAG, "Action URL : "+url);
// Get general information about the campaign
CampaignMetadata metadata = inAppMessage.getCampaignMetadata();
Log.i(TAG," Metadata : "+metadata);
}
#Override
public void impressionDetected(InAppMessage inAppMessage) {
LogUtils.i(TAG, "impressionDetected Action URL : "+inAppMessage.getCampaignMetadata().getCampaignName());
}
#Override
public void displayMessage(InAppMessage inAppMessage, FirebaseInAppMessagingDisplayCallbacks firebaseInAppMessagingDisplayCallbacks) {
LogUtils.i(TAG, "displayMessage Action URL : "+inAppMessage.getCampaignMetadata().getCampaignName());
}
}
And i register this click listener in MainActivity's onCreate
InAppMessageClick inAppMessageClick = new InAppMessageClick();
FirebaseInAppMessaging.getInstance().setMessageDisplayComponent(inAppMessageClick);
FirebaseInAppMessaging.getInstance().addClickListener(inAppMessageClick);
i tried to register listener for two ways.
InAppMessageClick inAppMessageClick = new InAppMessageClick();
FirebaseInAppMessaging.getInstance().addClickListener(inAppMessageClick);`
Or
FirebaseInAppMessaging.getInstance().addClickListener(inAppMessageClick, new Executor() {
#Override
public void execute(Runnable command) {
LogUtils.i("MainActivity", "FIAM CLICKED EXECUTOR");
}
});
`
And using gradle
implementation 'com.google.firebase:firebase-inappmessaging-display:18.0.2'
implementation 'com.google.firebase:firebase-core:17.0.1'
Could it be related to this issue opened 7 days ago?
https://github.com/firebase/firebase-android-sdk/issues/681
For some reason, FirebaseInAppMessaging remove all listeners every time an activity goes to background. You can see this by putting a break point on removeAllListeners method of DeveloperListenerManager class.
Registering your listener in the onResume method of your main activity is a way to deal with this problem.
Dependencies:
implementation platform('com.google.firebase:firebase-bom:26.6.0')
implementation 'com.google.firebase:firebase-analytics-ktx'
implementation 'com.google.firebase:firebase-inappmessaging-display-ktx'
implementation 'com.google.firebase:firebase-inappmessaging-ktx'
code on MainActivity onCreateMethod:
val firebaseIam = Firebase.inAppMessaging
firebaseIam.addClickListener { inAppMessage, action ->
//write your functionality
Log.d("here","successful)
}

Firebase JobDispatcher stops working after 1 hour

on API > 21 when my phone is locked this service is stop working (when I wake up a phone a service is starting working). This is what I do :
public class JobDispacherService extends JobService {
private Preferences prefs = null;
public static final String GCM_ONEOFF_TAG = "oneoff|[0,0]";
public static final String GCM_REPEAT_TAG = "komunalRepeat|[7200,1800]";
private static final String TAG = JobDispacherService.class.getSimpleName();
private UplaudPossitionTask uplaudPossitionTask;
#Override
public boolean onStartJob(#NonNull JobParameters job) {
uplaudPossitionTask = new UplaudPossitionTask() {
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
jobFinished(job, false);
}
};
uplaudPossitionTask.execute();
return false; // Answers the question: "Is there still work going on?"
}
#Override
public boolean onStopJob(JobParameters job) {
return true; // Answers the question: "Should this job be retried?"
}
private class UplaudPossitionTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
uploadPosition();
return null;
}
}
}
And I call this service just like this :
FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(context));
Job myJob = dispatcher.newJobBuilder()
.setService(JobDispacherService.class)
.setTag("my-unique-tag")
.setRecurring(true)
.setLifetime(Lifetime.FOREVER)
.setTrigger(Trigger.executionWindow(10, (int) 15))
.setReplaceCurrent(false)
.setRetryStrategy(RetryStrategy.DEFAULT_EXPONENTIAL)
.setConstraints(Constraint.ON_ANY_NETWORK)
.build();
dispatcher.mustSchedule(myJob);
I want to repeat this time all the time and I do not have idea why this service is stop wrking when my phone is locked more than 1h
WorkManager :
public static void refreshCouponPeriodicWork() {
//define constraints
Constraints myConstraints = new Constraints.Builder()
.setRequiresDeviceIdle(false)
.setRequiresCharging(false)
.setRequiredNetworkType(NetworkType.CONNECTED)
.setRequiresBatteryNotLow(true)
.setRequiresStorageNotLow(true)
.build();
Data source = new Data.Builder()
.putString("workType", "PeriodicTime")
.build();
PeriodicWorkRequest refreshCpnWork =
new PeriodicWorkRequest.Builder(RefreshLatestCouponWorker.class, 10, TimeUnit.HOURS,30, TimeUnit.SECONDS)
.setConstraints(myConstraints)
.setInputData(source)
.build();
WorkManager.getInstance().enqueue(refreshCpnWork);
}
public class RefreshLatestCouponWorker extends Worker {
private Preferences prefs = null;
public RefreshLatestCouponWorker(#NonNull Context context, #NonNull WorkerParameters workerParams) {
super(context, workerParams);
}
#NonNull
#Override
public Worker.Result doWork() {
//read input argument
String workType = getInputData().getString("workType");
Log.i("refresh cpn work", "type of work request: " + workType);
uploadPosition();
//sending work status to caller
return success();
}
}
I do this for work manager but task run only once and never is repeating
I suggest you read about WorkManager, that will be the correct solution for you. The WorkManager API makes it easy to schedule deferrable, asynchronous tasks that are expected to run even if the app exits or device restarts. You can define Periodic requests with specified time interval and device state. Revert in case you find the implementation difficult, i could help you with it.

One Service data Multiple Activity in android

Hi I make Android application for Xamarin. I have created a simple application in the Android studio. so any answer welcome either Java or C#
I have a service(GPS service) and 2 Activities.
MainActivity - GPS service are well connected with the broadcast. I hope MainActivity -> Another activity real time GPS point.(It is also okay to send from the GPS service to another activity.) but it is fail...app is dead..
MainActivity code
private void RegisterService()
{
_gpsServiceConnection = new GPSServiceConnection(_binder);
_gpsServiceIntent = new Intent(Android.App.Application.Context, typeof(GPS.GPSService));
BindService(_gpsServiceIntent, _gpsServiceConnection, Bind.AutoCreate);
}
private void RegisterBroadcastReceiver()
{
IntentFilter filter = new IntentFilter(GPSServiceReciever.LOCATION_UPDATED);
filter.AddCategory(Intent.CategoryDefault);
_receiver = new GPSServiceReciever();
RegisterReceiver(_receiver, filter);
}
private void UnRegisterBroadcastReceiver()
{
UnregisterReceiver(_receiver);
}
public void UpdateUI(Intent intent)
{
LatLng_txt.Text = intent.GetStringExtra("Location");
Lat = intent.GetDoubleExtra("Lat", 0.0);
Lng = intent.GetDoubleExtra("Lng", 0.0);
}
protected override void OnResume()
{
base.OnResume();
RegisterBroadcastReceiver();
}
protected override void OnPause()
{
base.OnPause();
UnRegisterBroadcastReceiver();
}
[BroadcastReceiver]
internal class GPSServiceReciever : BroadcastReceiver
{
public static readonly string LOCATION_UPDATED = "LOCATION_UPDATED";
public override void OnReceive(Context context, Intent intent)
{
if (intent.Action.Equals(LOCATION_UPDATED))
{
Instance.UpdateUI(intent);
}
}
}
GPS Service code
public void OnLocationChanged(Location location)
{
try
{
_currentLocation = location;
if (_currentLocation == null)
{
_location = "Unable to determine your location.";
}
else
{
_location = String.Format("{0}, {1}", _currentLocation.Latitude, _currentLocation.Longitude);
Geocoder geocoder = new Geocoder(this);
IList<Address> addressList = geocoder.GetFromLocation(_currentLocation.Latitude,
_currentLocation.Longitude, 10);
Address addressCurrent = addressList.FirstOrDefault();
if (addressCurrent != null)
{
StringBuilder deviceAddress = new StringBuilder();
for (int i = 0; i < addressCurrent.MaxAddressLineIndex; i++)
{
deviceAddress.Append(addressCurrent.GetAddressLine(i)).AppendLine(",");
}
_address = deviceAddress.ToString();
}
else
{
_address = "Unable to determine the address.";
}
IList<Address> source = geocoder.GetFromLocationName(_sourceAddress, 1);
Address addressOrigin = source.FirstOrDefault();
var coord1 = new LatLng(addressOrigin.Latitude, addressOrigin.Longitude);
var coord2 = new LatLng(addressCurrent.Latitude, addressCurrent.Longitude);
var distanceInRadius = Utils.HaversineDistance(coord1, coord2, Utils.DistanceUnit.Miles);
_remarks = string.Format("Your are {0} miles away from your original location.", distanceInRadius);
Intent intent = new Intent(this, typeof(MainActivity.GPSServiceReciever));
intent.SetAction(MainActivity.GPSServiceReciever.LOCATION_UPDATED);
intent.AddCategory(Intent.CategoryDefault);
intent.PutExtra("Location", _location);
intent.PutExtra("Lat", _currentLocation.Latitude);
intent.PutExtra("Lng", _currentLocation.Longitude);
SendBroadcast(intent);
}
}
catch
{
_address = "Unable to determine the address.";
}
}
Is not there a good way?
I understood your problem.But dont know more about GPS etc.I have faced the same problem when I was creating Music App.
Two activities were there and one service.And successfully got real time song position and song data from both activities.
My MainActivity has
ServiceConnection sc=null;
public static PlayerService ps;
And gets its value in onCreate of MainActivity
sc=new ServiceConnection(){
#Override
public void onServiceConnected(ComponentName p1, IBinder p2)
{
PlayerService.Getters getters=(PlayerService.Getters) p2;
ps=getters.getService();
}
#Override
public void onServiceDisconnected(ComponentName p1)
{
// TODO: Implement this method
}
};
Then PlayerService.Getters class is
public class Getters extends Binder
{
public PlayerService getService()
{
return PlayerService.this;
}
}
PlayerService has
#Override
public IBinder onBind(Intent p1)
{
return new Getters();
}
getService of Getters gives the object of PlayerService to my MainActivity.
Now I can get real time values of service variables and methods using static ps from multiple activities.
In order to send data or information from Service to Activity, you'll need to use Messenger API. This API will allow you to create an inter process communication (IPC) i.e. a communication link between two or more processes. In Android, Activity and Service are two separate processes, so you can use the IPC technique to establish a communication link in between them.
In the IPC technique, there are two ends, the Server end and the Client end. The Service acts as the Server and Activity acts as the Client.
Note: Service will only be able to communicate with one Activity at a time.
Messenger allows for the implementation of message-based communication across processes by help of Handlers.
Handler is a that allows you to send and process these messages.
Steps for implementing a Messenger:
Step 1. Service implements a Handler which receives the callbacks from the Activity
Step 2. The Handler then creates a Messenger object which further on creates an IBinder that the Service returns to the Activity.
Step 3. Activity then uses the IBinder to instantiate the Messenger, which the Activity uses to send messages to the Service.
Step 4. The Service receives the messages in the Handler created in the 1st step.
Lets now understand it with an example:
Create a Handler in the Service like this:
class ServiceHandler extends Handler {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
default:
super.handleMessage(msg);
}
}
}
Now, add the Messenger object along with onBind() method to the Service as mentioned in 2nd step above:
final Messenger messenger = new Messenger(new ServiceHandler());
#Override
public IBinder onBind(Intent intent) {
return messenger.getBinder();
}
In the Activity, we will create a ServiceConnection to fetch the iBinder from the Service to instantiate the Messenger object as mentioned in the 3rd step above.
Messenger messenger;
private ServiceConnection serviceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder iBinder) {
messenger = new Messenger(iBinder);
}
public void onServiceDisconnected(ComponentName className) {
}
};
Bind the Service to the Activity by help of the ServiceConnection created above:
bindService(new Intent(this, MessengerService.class), serviceConnection,
Context.BIND_AUTO_CREATE);
To send messages to the Service from the Activity, use the send() method of the Messenger object.
If you want to receive messages from the Service in the Activity, you need to create a Messenger in the Activity along with a Handler and use the replyTo parameter of the Messenger to receive messages to the respective Handler.

How to get a json from api using sync or wait for async task in android?

I've created a class to download raw data from url(api): GetRawData - GitHub
I extend the class:
GetTVShowDetailsJsonData - GitHub
So, my problem is, I call GetTVShowDetailsJsonData.java on my activity
public class ProcessTVShowsDetails extends GetTVShowDetailsJsonData {
private ProgressDialog progress;
public ProcessTVShowsDetails(TVShow show) {
super(show, TVShowDetailsActivity.this);
}
public void execute() {
// Start loading dialog
progress = ProgressDialog.show(TVShowDetailsActivity.this, "Aguarde...", "Estamos carregando os dados da série.", true);
// Start process data (download and get)
ProcessData processData = new ProcessData();
processData.execute();
}
public class ProcessData extends DownloadJsonData {
protected void onPostExecute(String webData) {
super.onPostExecute(webData);
mTVShowDetails = getTVShowsDetails();
bindParams();
// Close loading dialog.
if (progress.isShowing()) progress.dismiss();
}
}
}
But inside this call, I want to call another download another JSON from other url, using GetSeasonJsonData.java, is the same GetTVShowDetailsJsonData.java do, but for another PARSE.I need to wait the task being completed or maybe do in synchronous way, to add the result from GetSeasonJsonData.java inside the first result from GetTvShowDetailsJsonData. How can I do that?
Just a note, i need to run more than one time, and I already try this, but doesn't work:
// Process and execute data into recycler view
public class ProcessTVShowsDetails extends GetTVShowDetailsJsonData {
private ProgressDialog progress;
public ProcessTVShowsDetails(TVShow show) {
super(show, TVShowDetailsActivity.this);
}
public void execute() {
// Start loading dialog
progress = ProgressDialog.show(TVShowDetailsActivity.this, "Aguarde...", "Estamos carregando os dados da série.", true);
// Start process data (download and get)
ProcessData processData = new ProcessData();
processData.execute();
}
public class ProcessData extends DownloadJsonData {
protected void onPostExecute(String webData) {
super.onPostExecute(webData);
mTVShowDetails = getTVShowsDetails();
//Process SeasonData
for(int seasonNumber = 1; seasonNumber <= mTVShowDetails.getNumberOfSeasons(); seasonNumber++) {
ProcessSeason processSeason = new ProcessSeason(mTVShowDetails.getId(), seasonNumber);
processSeason.execute();
}
bindParams();
// Close loading dialog.
if (progress.isShowing()) progress.dismiss();
}
}
}
// Process Season Data
public class ProcessSeason extends GetTVShowSeasonJsonData {
public ProcessSeason(int showId, int serieNumber) {
super(showId, serieNumber, TVShowDetailsActivity.this);
}
public void execute() {
// Start process data (download and get)
ProcessData processData = new ProcessData();
processData.execute();
}
public class ProcessData extends DownloadJsonData {
protected void onPostExecute(String webData) {
super.onPostExecute(webData);
}
}
}

Adobe Air ANE for android with java native extension trying to receive broadcast

I'm trying to create a native extension which can receive broadcasts, sent from a native android am as intent broadcasts.
The sending part works, I've tested this with a native app that has a broadcast receiver, but I cant get it to work in the native extension.
Here's what I have so far:
Here the java side of the ANE
public class ReceiverPhidget extends BroadcastReceiver {
private FREContext mFREContext;
public ReceiverPhidget(FREContext mFREContext) {
this.mFREContext = mFREContext;
}
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(IntentsKeys.INTENT_PHIDGET_CONNECTED)){
//Send listener in ANE project with message that phidget connected (not must)
System.out.println("Phidget connected");
mFREContext.dispatchStatusEventAsync("Yes", Keys.KEY_CONNECTED);
} else
if (action.equals(IntentsKeys.INTENT_PHIDGET_DISCONNECTED)){
//Send listener in ANE project with message that phidget disconnected (not must)
System.out.println("Phidget disconnected");
mFREContext.dispatchStatusEventAsync("Yes", Keys.KEY_DISCONNECTED);
} else
if (action.equals(IntentsKeys.INTENT_PHIDGET_GAIN_TAG)){
//Send listener with data in ANE project with message that phidget gain receive
String message = intent.getStringExtra(IntentsKeys.INTENT_PHIDGET_EXTRA_DATA);
System.out.println("Phidget gain message: " + message);
Log.d("TAG FOUND", message);
mFREContext.dispatchStatusEventAsync(message, Keys.KEY_TAG_GAIN);
}
}
public static IntentFilter getIntentFilter(){
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(IntentsKeys.INTENT_PHIDGET_CONNECTED);
intentFilter.addAction(IntentsKeys.INTENT_PHIDGET_DISCONNECTED);
intentFilter.addAction(IntentsKeys.INTENT_PHIDGET_GAIN_TAG);
return intentFilter;
}
}
And the FREExtension
public class ReceiverExtension implements FREExtension {
private ReceiverPhidget mReceiverPhidget;
private ReceiverExtensionContext mContext;
#Override
public void initialize() {
mReceiverPhidget = new ReceiverPhidget(mContext);
mContext.getActivity().registerReceiver(mReceiverPhidget, ReceiverPhidget.getIntentFilter());
}
#Override
public FREContext createContext(String s) {
return mContext = new ReceiverExtensionContext();
}
#Override
public void dispose() {
mContext.getActivity().unregisterReceiver(mReceiverPhidget);
}
}
And here is the flash library side of the ANE
package nl.mediaheads.anetest.extension {
import flash.events.EventDispatcher;
import flash.events.StatusEvent;
import flash.external.ExtensionContext;
public class RFIDController extends EventDispatcher {
private var extContext:ExtensionContext;
private var channel:int;
private var scannedChannelList:Vector.<int>;
public function RFIDController() {
extContext = ExtensionContext.createExtensionContext(
"nl.mediaheads.anetest.exntension.RFIDController", "");
extContext.addEventListener(StatusEvent.STATUS, onStatus);
}
private function onStatus(event:StatusEvent):void {
if (event.level == EventKeys.KEY_TAG_GAIN) {
dispatchEvent (new TagEvent(TagEvent.TAG_GAINED, event.code) );
}
}
}
}
And here is my test mobile project class to test the ANE
package
{
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.text.TextField;
import nl.mediaheads.anetest.extension.RFIDController;
[SWF(width="1280", height="800", frameRate="60", backgroundColor="#ffffff")]
public class AneTestApp extends Sprite
{
private var tf:TextField;
private var rc:RFIDController;
public function AneTestApp()
{
super();
// support autoOrients
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.color = 0xFFFFFF;
addEventListener(Event.ADDED_TO_STAGE, onAdded);
}
private function onAdded(event:Event):void {
//
tf = new TextField();
tf.width = 200;
tf.height = 50;
tf.x = 10;
tf.y = 64;
tf.mouseEnabled = false;
tf.background = true;
tf.backgroundColor = 0xF50000;
addChild(tf);
rc = new RFIDController();
tf.text = "test 1";
this.addEventListener( TagEvent.TAG_GAINED , onTagAdded);
tf.text = "test 2";
//
}
private function onTagAdded(event:TagEvent):void
{
tf.text = event.params;
}
}
}
I have signed the ANE accordingly, I also signed the test app it's self.
I have a Log.d in the java part of the ANE which should pop up on log cat but it doesn't, also the textfield just becomes blank as soon as I initialized the RFIDController even without added the event listener.
If you need any more code or information to help me solve this problem feel free to ask.
I could really use some help because I'm completely lost, I've followed multiple tutorials and guide on how to do this, I should have done everything correctly, but I clearly have not.
UPDATE: 1
The extension xml
<extension xmlns="http://ns.adobe.com/air/extension/3.5">
<id>nl.mediaheads.anetest.exntension.RFIDController</id>
<versionNumber>0.0.1</versionNumber>
<platforms>
<platform name="Android-ARM">
<applicationDeployment>
<nativeLibrary>AneTest.jar</nativeLibrary>
<initializer>nl.mediaheads.anetest.ReceiverExtension</initializer>
<finalizer>nl.mediaheads.anetest.ReceiverExtension</finalizer>
</applicationDeployment>
</platform>
</platforms>
</extension>
UPDATE 2:
I fixed it, it was an context issue together with that flash somehow clean my custom event so I used status event to parse from the flash side of the ANE to the air application itself.
Currently you are creating your receiver at the initialisation point of the extension which will most likely be called before the context creation, so your context may be null at that point and causing your errors.
Try moving the creation of your ReceiverPhidget to the constructor of your ReceiverExtensionContext. Something like the following (I haven't tested this):
public class ReceiverExtensionContext extends FREContext
{
private ReceiverPhidget mReceiverPhidget;
public ReceiverExtensionContext()
{
mReceiverPhidget = new ReceiverPhidget( this );
getActivity().registerReceiver( mReceiverPhidget, ReceiverPhidget.getIntentFilter() );
}
#Override
public Map<String, FREFunction> getFunctions()
{
Map<String, FREFunction> functionMap = new HashMap<String, FREFunction>();
return functionMap;
}
#Override
public void dispose()
{
getActivity().unregisterReceiver( mReceiverPhidget );
}
}

Categories

Resources