Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

Doh004 posted:

Gotcha, that's more related to app support which is good to know - I'm actually asking about the business development people? Who manages the Play Store categories? How do you get featured more prominently? Set up partnerships between the two etc.

I do not know the answer to your questions, but I do know Google. I would bet that its almost all algorithmic.

Adbot
ADBOT LOVES YOU

John F Bennett
Jan 30, 2013

I always wear my wedding ring. It's my trademark.

Doh004 posted:

Gotcha, that's more related to app support which is good to know - I'm actually asking about the business development people? Who manages the Play Store categories? How do you get featured more prominently? Set up partnerships between the two etc.

I'm not an expert or anything but I'm not sure that's really a thing? You have the usual app store optimization tips you can study , using keywords etc...

Or spend a bunch of money on marketing I suppose.

Doh004
Apr 22, 2007

Mmmmm Donuts...

Thermopyle posted:

I do not know the answer to your questions, but I do know Google. I would bet that its almost all algorithmic.

John F Bennett posted:

I'm not an expert or anything but I'm not sure that's really a thing? You have the usual app store optimization tips you can study , using keywords etc...

Or spend a bunch of money on marketing I suppose.

That's what we figured! We're much more established on the App Store, so trying to break into the Play Store has been an interesting learning experience. Thanks for the responses :)

Tunga
May 7, 2004

Grimey Drawer
The best way to get featured is to be a known brand and then wait for Google to approach you about some new tech they have in the works. My company was asked if we wanted to be part of the Android Pay launch in the UK, for example, but we were tied up with other things and didn't think it would be that big so business people declined.

I realise that "be a known brand" is not a thing you can just do.

Doh004
Apr 22, 2007

Mmmmm Donuts...

Tunga posted:

The best way to get featured is to be a known brand and then wait for Google to approach you about some new tech they have in the works. My company was asked if we wanted to be part of the Android Pay launch in the UK, for example, but we were tied up with other things and didn't think it would be that big so business people declined.

We were hoping to avoid the wait! We are a known brand and one of the few mealkit companies on Google Play. I'll just relay to folks even more patience :)

kitten smoothie
Dec 29, 2001

If you're paying for any other sort of Google services and have an account manager person at Google to contact over it, like GSuite, GCP, etc, I might at least try going to them and seeing if you can't get an introduction to a Play bizdev person that way.

Otherwise afaict it's "don't call us, we'll call you."

FAT32 SHAMER
Aug 16, 2012



I'm trying to verify that my app is receiving UDP traffic from port 12001 to rule out the app being broken and see if the device sending the UDP signals (a vehicle) is actually sending them. What's the best way to do this? there seems to be a lot of sniffers on the play store but they seem to require connection to a VPN and they seem to be dodgy.

I need a solution that doesnt require a rooted device as well

Vesi
Jan 12, 2005

pikachu looking at?

FAT32 SHAMER posted:

I'm trying to verify that my app is receiving UDP traffic from port 12001 to rule out the app being broken and see if the device sending the UDP signals (a vehicle) is actually sending them. What's the best way to do this? there seems to be a lot of sniffers on the play store but they seem to require connection to a VPN and they seem to be dodgy.

I need a solution that doesnt require a rooted device as well

these are two separate problems, you can test UDP receiving by sending data with for example netcat if you're in the same network
pre:
$ echo asd|nc -u <phone-ip> 12001
remember to ask the user to disable battery optimizations first:
https://developer.android.com/training/monitoring-device-state/doze-standby.html

also UDP seems like an awful idea in 2017, but maybe you don't have a choice?

FAT32 SHAMER
Aug 16, 2012



Vesi posted:

these are two separate problems, you can test UDP receiving by sending data with for example netcat if you're in the same network
pre:
$ echo asd|nc -u <phone-ip> 12001
remember to ask the user to disable battery optimizations first:
https://developer.android.com/training/monitoring-device-state/doze-standby.html

also UDP seems like an awful idea in 2017, but maybe you don't have a choice?

it's for vehicle to vehicle communications so you can imagine what i'm dealing with :saddowns:

Hughlander
May 11, 2005

Vesi posted:

these are two separate problems, you can test UDP receiving by sending data with for example netcat if you're in the same network
pre:
$ echo asd|nc -u <phone-ip> 12001

remember to ask the user to disable battery optimizations first:
https://developer.android.com/training/monitoring-device-state/doze-standby.html

also UDP seems like an awful idea in 2017, but maybe you don't have a choice?

For a mobile device where the time the radio is on is directly correlated to battery life, why is UDP bad? I’ve personally had to do a lot of work around batching up network traffic to give double digit battery gains and if I could have used UDP for it, I would have in a heart beat.

FAT32 SHAMER
Aug 16, 2012



I asked the big brains and the reason for using UDP is so vehicles can communicate their location quicker without worrying about a response packet and can get away with missing information.

Vesi
Jan 12, 2005

pikachu looking at?

Hughlander posted:

For a mobile device where the time the radio is on is directly correlated to battery life, why is UDP bad? I’ve personally had to do a lot of work around batching up network traffic to give double digit battery gains and if I could have used UDP for it, I would have in a heart beat.

UDP handles firewalls/NAT very inconsistently, and if you want to do anything serious with it you'll probably re-invent the TCP wheel badly. With TCP you already have full control over how often you send the connection keepalive packets (if you control the server that is) so there shouldn't be any battery saving either.

UDP is great for:
* If your bandwidth is so tiny you can't handle the ~40 bytes in response packets
* If your data is literally garbage and can afford to throw it into a black hole without ever knowing what happens to it
* DNS

Vesi fucked around with this message at 21:31 on Jul 11, 2017

b0lt
Apr 29, 2005

Vesi posted:

UDP handles firewalls/NAT very inconsistently

This is especially bad, because lots of mobile networks are using carrier NAT now.

Hughlander
May 11, 2005

Vesi posted:

UDP handles firewalls/NAT very inconsistently, and if you want to do anything serious with it you'll probably re-invent the TCP wheel badly. With TCP you already have full control over how often you send the connection keepalive packets (if you control the server that is) so there shouldn't be any battery saving either.

UDP is great for:
* If your bandwidth is so tiny you can't handle the ~40 bytes in response packets
* If your data is literally garbage and can afford to throw it into a black hole without ever knowing what happens to it
* DNS

...
Places where you want to transparently handle IP address changes. (Wifi to cell, to different wifi)
Places where you only care about the most recent set of data and don’t need to block on a dropped radio packet
Places where you’re already talking to a known and fixed address and never need to NAT negotiate

As in, in the case that I used it action games.

Sereri
Sep 30, 2008

awwwrigami

Is there a kotlin thread? Is this the kotlin thread?

Taffer
Oct 15, 2010


Sereri posted:

Is there a kotlin thread? Is this the kotlin thread?

This is the kotlin thread!

Sereri
Sep 30, 2008

awwwrigami

Mostly an observation (and possibly borderline racist):

My Chinese coworker has stereotypical problems with r and l sounding similar.
val / var seems to be unnecessarily asking for trouble as you could have named one of them basically anything else.

baka kaba
Jul 19, 2003

PLEASE ASK ME, THE SELF-PROFESSED NO #1 PAUL CATTERMOLE FAN IN THE SOMETHING AWFUL S-CLUB 7 MEGATHREAD, TO NAME A SINGLE SONG BY HIS EXCELLENT NU-METAL SIDE PROJECT, SKUA, AND IF I CAN'T PLEASE TELL ME TO
EAT SHIT

Do most language designers even think about non-(native) English speakers?

I don't think that's racist though, 'l' and 'r' (especially the English 'r') don't really exist as separate sounds in a lot of languages, so some people never learn to hear or produce them both easily

Of course var has no 'r' sound as god intended

Volmarias
Dec 31, 2002

EMAIL... THE INTERNET... SEARCH ENGINES...
Ask your coworker what the phonetic pronunciations of Value and Variable are in their native tongue, use shortened values of that.

Tunga
May 7, 2004

Grimey Drawer
The "a" phoneme is different between "var" and "val". Also how often are you dictating code to each other?

FAT32 SHAMER
Aug 16, 2012



Ok boyos who wants so Stack Exchange e-points

https://stackoverflow.com/questions/45090837/nullpointerexception-on-asynctask-execute

dont let EE's write loving android apps

baka kaba
Jul 19, 2003

PLEASE ASK ME, THE SELF-PROFESSED NO #1 PAUL CATTERMOLE FAN IN THE SOMETHING AWFUL S-CLUB 7 MEGATHREAD, TO NAME A SINGLE SONG BY HIS EXCELLENT NU-METAL SIDE PROJECT, SKUA, AND IF I CAN'T PLEASE TELL ME TO
EAT SHIT

I can't see which is line 61 of MainActivity (where you're calling a method on a null object) but I'm guessing you're meant to be assigning to an mListeningService field in onCreate instead of creating a local variable?

FAT32 SHAMER
Aug 16, 2012



baka kaba posted:

I can't see which is line 61 of MainActivity (where you're calling a method on a null object) but I'm guessing you're meant to be assigning to an mListeningService field in onCreate instead of creating a local variable?

Yeah I marked it here. The EE created the mAndroidUDP.startIt() method which looks like this

Java code:
    public void startIt() {

        listeningService.continueListening();

    }
and continueListening() simply has new startListening().execute() where startListening extends AsyncTask

Here's the onCreate method

Java code:
@Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        

        // init parameters
        started = false;
        counter = 0;

        IntentFilter filter =  new IntentFilter("ToActivity");

        mAndroidUDP = new AndroidUDP(this, this);
        mAndroidUDP.intent1 = new Intent(this, ListeningService.class);
        mAndroidUDP.intent2 = new Intent(this, PlaySound.class);
        startService(mAndroidUDP.intent1);
        startService(mAndroidUDP.intent2);

        mAndroidUDP.doStuff(this,filter);
        mAndroidUDP.startIt(); //this is the cause of the Null Object Reference


        mImageView = (ImageView) this.findViewById(R.id.image_view);

        mTextView = (TextView) findViewById(R.id.alert_text);
        mBlinkView = (TextView) findViewById(R.id.blinking_text);

        Animation mAnimation = new AlphaAnimation(0.0f, 1.0f);
        mAnimation.setDuration(100);
        mAnimation.setStartOffset(20);
        mAnimation.setRepeatCount(Animation.INFINITE);
        mAnimation.setRepeatMode(Animation.REVERSE);
        mBlinkView.startAnimation(mAnimation);
    }
If this wasnt due by monday of next week I would have just torn it all down and rebuilt it instead of trying to debug it and deal with this lovely code. I still have no idea why he decided to use enumerations and ordinal arrays over just using a dictionary/map and assigning the image and alert sounds as properties

baka kaba
Jul 19, 2003

PLEASE ASK ME, THE SELF-PROFESSED NO #1 PAUL CATTERMOLE FAN IN THE SOMETHING AWFUL S-CLUB 7 MEGATHREAD, TO NAME A SINGLE SONG BY HIS EXCELLENT NU-METAL SIDE PROJECT, SKUA, AND IF I CAN'T PLEASE TELL ME TO
EAT SHIT

Where's listeningService getting assigned in AndroidUDP?

FAT32 SHAMER
Aug 16, 2012



baka kaba posted:

Where's listeningService getting assigned in AndroidUDP?

Java code:
public class AndroidUDP extends Service
{



    enum alerts
    {
        ALERT_CLEAR, //0
        ALERT_FCW_IMMINENT, //1
        ALERT_DNPW_IMMINENT, //2
        ALERT_IMA_IMMINENT_LEFT, //3
        ALERT_IMA_IMMINENT_RIGHT, //4
        ALERT_CLW_IMMINENT, //5
        ALERT_LCW_IMMINENT_LEFT, //6
        ALERT_LCW_IMMINENT_RIGHT, //7
        ALERT_BSW_IMMINENT_LEFT, //8
        ALERT_BSW_IMMINENT_RIGHT, //9
        ALERT_FCW_ADVISORY, //10
        ALERT_DNPW_ADVISORY, //11
        ALERT_IMA_ADVISORY_LEFT, //12
        ALERT_IMA_ADVISORY_RIGHT, //13
        ALERT_BSW_ADVISORY_LEFT, //14
        ALERT_BSW_ADVISORY_RIGHT, //15
        ALERT_LTA_ADVISORY_LEFT, //16
        ALERT_LTA_ADVISORY_RIGHT, //17
        ALERT_LTA_ADVISORY_OPPOSITE //18
    }

    MainActivity mainActivity;
    ListeningService listeningService;
    PlaySound soundAlert;
    public Intent intent1;
    public Intent intent2;
    Integer alarmImages[];

    String alertTextMessages[];
    String imminentTextMessages[];
    Context context;

    public boolean on;

    int sendAlarm;

    public AndroidUDP() {

    }


    public AndroidUDP(MainActivity r, Context c)
    {
        on = false;
        sendAlarm = alerts.ALERT_CLEAR.ordinal();
        mainActivity = r;
        context = c;


        alarmImages = new Integer[19];
        alarmImages[alerts.ALERT_CLEAR.ordinal()] = R.drawable.image_all_clear;
        alarmImages[alerts.ALERT_FCW_IMMINENT.ordinal()] = R.drawable.image_fcw_imminent;
        alarmImages[alerts.ALERT_DNPW_IMMINENT.ordinal()] = R.drawable.image_dnpw_imminent;
        alarmImages[alerts.ALERT_IMA_IMMINENT_LEFT.ordinal()] = R.drawable.image_ima_imminent_left;
        alarmImages[alerts.ALERT_IMA_IMMINENT_RIGHT.ordinal()] = R.drawable.image_ima_imminent_right;
        alarmImages[alerts.ALERT_CLW_IMMINENT.ordinal()] = R.drawable.image_clw_imminent;
        alarmImages[alerts.ALERT_LCW_IMMINENT_LEFT.ordinal()] = R.drawable.image_lcw_imminent_left;
        alarmImages[alerts.ALERT_LCW_IMMINENT_RIGHT.ordinal()] = R.drawable.image_lcw_imminent_right;
        alarmImages[alerts.ALERT_BSW_IMMINENT_LEFT.ordinal()] = R.drawable.image_bsw_imminent_left;
        alarmImages[alerts.ALERT_BSW_IMMINENT_RIGHT.ordinal()] = R.drawable.image_bsw_imminent_right;

        alarmImages[alerts.ALERT_FCW_ADVISORY.ordinal()] = R.drawable.image_fcw_advisory;
        alarmImages[alerts.ALERT_DNPW_ADVISORY.ordinal()] = R.drawable.image_dnpw_advisory;
        alarmImages[alerts.ALERT_IMA_ADVISORY_LEFT.ordinal()] = R.drawable.image_ima_advisory_left;
        alarmImages[alerts.ALERT_IMA_ADVISORY_RIGHT.ordinal()] = R.drawable.image_ima_advisory_right;
        alarmImages[alerts.ALERT_BSW_ADVISORY_LEFT.ordinal()] = R.drawable.image_bsw_advisory_left;
        alarmImages[alerts.ALERT_BSW_ADVISORY_RIGHT.ordinal()] = R.drawable.image_bsw_advisory_right;
        alarmImages[alerts.ALERT_LTA_ADVISORY_LEFT.ordinal()] = R.drawable.image_lta_advisory_left;
        alarmImages[alerts.ALERT_LTA_ADVISORY_RIGHT.ordinal()] = R.drawable.image_lta_advisory_right;
        alarmImages[alerts.ALERT_LTA_ADVISORY_OPPOSITE.ordinal()] = R.drawable.image_lta_advisory_opposite;

        alertTextMessages = new String[19];
        alertTextMessages[alerts.ALERT_CLEAR.ordinal()] = "ALL CLEAR";
        alertTextMessages[alerts.ALERT_FCW_ADVISORY.ordinal()] = "FORWARD COLLISION ALERT";
        alertTextMessages[alerts.ALERT_DNPW_ADVISORY.ordinal()] = "DO NOT PASS ALERT";
        alertTextMessages[alerts.ALERT_IMA_ADVISORY_LEFT.ordinal()] = "LEFT INTERSECTION MOVEMENT ALERT";
        alertTextMessages[alerts.ALERT_IMA_ADVISORY_RIGHT.ordinal()] = "RIGHT INTERSECTION MOVEMENT ALERT";
        alertTextMessages[alerts.ALERT_BSW_ADVISORY_LEFT.ordinal()] = "LEFT BLIND SPOT ALERT";
        alertTextMessages[alerts.ALERT_BSW_ADVISORY_RIGHT.ordinal()] = "RIGHT BLIND SPOT ALERT";
        alertTextMessages[alerts.ALERT_LTA_ADVISORY_LEFT.ordinal()] = "LEFT LEFT TURN ASSIST ALERT";
        alertTextMessages[alerts.ALERT_LTA_ADVISORY_RIGHT.ordinal()] = "RIGHT LEFT TURN ASSIST ALERT";
        alertTextMessages[alerts.ALERT_LTA_ADVISORY_OPPOSITE.ordinal()] = "OPPOSITE LEFT TURN ASSIST ALERT";

        imminentTextMessages = new String[19];
        imminentTextMessages[alerts.ALERT_FCW_IMMINENT.ordinal()] = "FORWARD COLLISION IMMINENT";
        imminentTextMessages[alerts.ALERT_DNPW_IMMINENT.ordinal()] = "DO NOT PASS IMMINENT";
        imminentTextMessages[alerts.ALERT_IMA_IMMINENT_LEFT.ordinal()] = "LEFT INTERSECTION MOVEMENT IMMINENT";
        imminentTextMessages[alerts.ALERT_IMA_IMMINENT_RIGHT.ordinal()] = "RIGHT INTERSECTION MOVEMENT IMMINENT";
        imminentTextMessages[alerts.ALERT_CLW_IMMINENT.ordinal()]= "CONTROL LOSS IMMINENT";
        imminentTextMessages[alerts.ALERT_LCW_IMMINENT_LEFT.ordinal()] = "IMMINENT LEFT LANE CHANGE";
        imminentTextMessages[alerts.ALERT_LCW_IMMINENT_RIGHT.ordinal()] = "IMMINENT RIGHT LANE CHANGE";
        imminentTextMessages[alerts.ALERT_BSW_IMMINENT_LEFT.ordinal()] = "IMMINENT LEFT BLIND SPOT";
        imminentTextMessages[alerts.ALERT_BSW_IMMINENT_RIGHT.ordinal()] = "IMMINENT RIGHT BLIND SPOT";


    }

    ////creating broadcast receiver
    private BroadcastReceiver heard_reception = new BroadcastReceiver()
    {
        @Override
        public void onReceive(Context context, Intent intent)
        {

            //Toast.makeText(context, P, Toast.LENGTH_SHORT).show();

            String P = listeningService.the_alarm_S;
            String A[] = P.split("!!!");


            if(Integer.valueOf(A[1]) >= 0 && Integer.valueOf(A[1]) <= alerts.ALERT_CLEAR.ordinal() && on)
            {
                if(sendAlarm == alerts.ALERT_CLEAR.ordinal())
                {
                    sendAlarm = Integer.valueOf( A[1] );
                    repeatAlarm();       // start recursive function
                }
                else
                {
                    sendAlarm = Integer.valueOf( A[1] );

                    // remove at end
                    repeatAlarm();
                }
            }
        }
    };

    public void repeatAlarm()
    {
        MainActivity.mImageView.setImageResource( alarmImages[sendAlarm] );

        Animation mAnimation = new AlphaAnimation(0.0f, 1.0f);
        mAnimation.setDuration(50);
        mAnimation.setStartOffset(20);
        mAnimation.setRepeatCount(Animation.INFINITE);
        mAnimation.setRepeatMode(Animation.REVERSE);
        MainActivity.mBlinkView.startAnimation(mAnimation); //animation value

        MainActivity.mBlinkView.setText(imminentTextMessages[sendAlarm]);
        MainActivity.mTextView.setText(alertTextMessages[sendAlarm]);



        if(sendAlarm >= 1 || sendAlarm <= 9 && sendAlarm != 0) {
            MainActivity.mTextView.setText(alertTextMessages[sendAlarm]);
        } else {
            MainActivity.mBlinkView.setText(imminentTextMessages[sendAlarm]);
        }


        //soundAlert.sendAlarm2 = sendAlarm;
        soundAlert.playIt(sendAlarm);


        //Toast.makeText(context, String.valueOf(sendAlarm), Toast.LENGTH_SHORT).show();

    }


    public void stopAll()
    {

        soundAlert.stopIt();
    }


    public void doStuff(MainActivity r, IntentFilter filter)
    {
        mainActivity = r;

        mainActivity.bindService(intent1, serviceConn1, Context.BIND_AUTO_CREATE);
        mainActivity.registerReceiver(heard_reception, filter);

        mainActivity.bindService(intent2, serviceConn2, Context.BIND_AUTO_CREATE);

    }


    public void startIt()
    {

        listeningService = new ListeningService();
        listeningService.intent1 = new Intent(this, ListeningService.class);
        startService(listeningService.intent1);

        listeningService.continueListening();

    }

    ////creating service connection
    ServiceConnection serviceConn1 = new ServiceConnection()
    {
        //service unbound, release from memory
        @Override
        public void onServiceDisconnected(ComponentName name)
        {

            listeningService = null;
        }

        //service is bound, start it's work
        @Override
        public void onServiceConnected(ComponentName name, IBinder service)
        {
            listeningService = ((ListeningService.LocalBinder)service).getService();

        }
    };

    ////creating service connection
    ServiceConnection serviceConn2 = new ServiceConnection()
    {
        //service unbound, release from memory
        @Override
        public void onServiceDisconnected(ComponentName name)
        {

            soundAlert = null;
        }

        //service is bound, start it's work
        @Override
        public void onServiceConnected(ComponentName name, IBinder service)
        {
            soundAlert = ((PlaySound.LocalBinder)service).getService();
        }
    };

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

}
I hope none of you get cancer after reading this.

They havent had real programmers in the company until like March and now that we have some down time theyre coming to us to fix their broken code that's due tomorrow at 3p pls can u make this work!!!

My existence is pain

FAT32 SHAMER fucked around with this message at 23:26 on Jul 13, 2017

baka kaba
Jul 19, 2003

PLEASE ASK ME, THE SELF-PROFESSED NO #1 PAUL CATTERMOLE FAN IN THE SOMETHING AWFUL S-CLUB 7 MEGATHREAD, TO NAME A SINGLE SONG BY HIS EXCELLENT NU-METAL SIDE PROJECT, SKUA, AND IF I CAN'T PLEASE TELL ME TO
EAT SHIT

I haven't done a lot with services and there's a bunch of weird stuff in there (what's listeningService.intent1, I don't see that field? What's with creating a ListeningService with new?) that should stop it running at all, I'm guessing you're trying to cut out code so it's not all over the internets but it's hard to look through

You could try this

Java code:
public void startIt()
{
    Intent intent = new Intent(this, ListeningService.class);
    startService(intent);
}
That's generally how it goes
  • you call startService() with an an intent for the service class you want
  • onStartCommand() gets called in that service
in your onStartCommand you're already calling continueListening(), so no need to do it in the startIt() method. (In fact right now it's getting called on the instance you newed which isn't initialised as a service

The binding stuff... it's referring to intent1 which isn't initialised anywhere, and maybe that's the mysterious listeningService.intent1 and... yeah this is hard to follow. It's hard to know if this will break anything, you can always try it



Otherwise get your debugger open, stick a watch on that listeningService variable that's going null and see what's doing it :shrug:

b0lt
Apr 29, 2005
You're sending imminent forward collision alerts via UDP?

FAT32 SHAMER
Aug 16, 2012



b0lt posted:

You're sending imminent forward collision alerts via UDP?

That's exactly what I said

baka kaba posted:

I haven't done a lot with services and there's a bunch of weird stuff in there (what's listeningService.intent1, I don't see that field? What's with creating a ListeningService with new?) that should stop it running at all, I'm guessing you're trying to cut out code so it's not all over the internets but it's hard to look through

You could try this

Java code:

public void startIt()
{
    Intent intent = new Intent(this, ListeningService.class);
    startService(intent);
}

That's generally how it goes
  • you call startService() with an an intent for the service class you want
  • onStartCommand() gets called in that service
in your onStartCommand you're already calling continueListening(), so no need to do it in the startIt() method. (In fact right now it's getting called on the instance you newed which isn't initialised as a service

The binding stuff... it's referring to intent1 which isn't initialised anywhere, and maybe that's the mysterious listeningService.intent1 and... yeah this is hard to follow. It's hard to know if this will break anything, you can always try it



Otherwise get your debugger open, stick a watch on that listeningService variable that's going null and see what's doing it :shrug:

Thanks for this, I'll see how it goes tomorrow when I get in

FAT32 SHAMER
Aug 16, 2012



I decided to say gently caress it and instead of trying to use the listener as a service, just use an AsyncTask as an inner class of the main activity because it's a single activity app and there's no reason to overcomplicate it like the original guy did. Stupid question time: in the onPostExecution I understand that this would be where I set the text/image of my TextView and ImageView. According to this stackoverflow question

quote:

If this is an inner class of your Activity then initialize the View in the Activity then update it in your task as described above.
I'm assuming he's saying "initialize the MainActivity's View in the inner class" but i can't parse this because it's friday and i'm retarded

baka kaba
Jul 19, 2003

PLEASE ASK ME, THE SELF-PROFESSED NO #1 PAUL CATTERMOLE FAN IN THE SOMETHING AWFUL S-CLUB 7 MEGATHREAD, TO NAME A SINGLE SONG BY HIS EXCELLENT NU-METAL SIDE PROJECT, SKUA, AND IF I CAN'T PLEASE TELL ME TO
EAT SHIT

They're saying hold the reference in the activity class, initialise it with findViewById when the activity is setting up (like in onCreateView) and then just refer to that from your AsyncTask

FAT32 SHAMER
Aug 16, 2012



baka kaba posted:

They're saying hold the reference in the activity class, initialise it with findViewById when the activity is setting up (like in onCreateView) and then just refer to that from your AsyncTask

If I reference it from onCreate that causes a static/nonstatic error, wouldn't it?

baka kaba
Jul 19, 2003

PLEASE ASK ME, THE SELF-PROFESSED NO #1 PAUL CATTERMOLE FAN IN THE SOMETHING AWFUL S-CLUB 7 MEGATHREAD, TO NAME A SINGLE SONG BY HIS EXCELLENT NU-METAL SIDE PROJECT, SKUA, AND IF I CAN'T PLEASE TELL ME TO
EAT SHIT

Nah you have a non-static TextView field or whatever in your activity, assign it when you can grab a reference to the actual View after it's been inflated. onCreateView is the best time to do this - inflate your layout, do your findViewById stuff to pluck out the Views you want references to, then return the inflated layout view as usual

Then with your AsyncTask as an inner class of the activity it can access that reference. Just make sure it doesn't try to access it before you've actually set it - so start your task after the view field is assigned

(You can't grab the view in onCreate because you haven't inflated your layout yet)

FAT32 SHAMER
Aug 16, 2012



baka kaba posted:

Nah you have a non-static TextView field or whatever in your activity, assign it when you can grab a reference to the actual View after it's been inflated. onCreateView is the best time to do this - inflate your layout, do your findViewById stuff to pluck out the Views you want references to, then return the inflated layout view as usual

Then with your AsyncTask as an inner class of the activity it can access that reference. Just make sure it doesn't try to access it before you've actually set it - so start your task after the view field is assigned

(You can't grab the view in onCreate because you haven't inflated your layout yet)

Ahhh that explains a lot. I always forget about the difference between the two

FAT32 SHAMER
Aug 16, 2012



So I successfully got my AsyncTask working and it receives the data that is pinged to it and changes the ImageView and TextView based on what the message says when parsed. It works almost exactly how I'd like it to except for one problem: you have to press the button multiple times, which means if the packet data changes, you have to be clicking it quite frequently to get the update. I attempted to use a ToggleButton with a while loop to continuously run the AsyncTask while the ToggleButton had .isChecked = true, however as you can imagine this caused it to crash due to what I assume was too much data on the UI thread.

So based on this, I believe that I need to rewrite this as a service so that it can run on its own thread and not kill everything. This is what my AsyncTask currently looks like:

Java code:
public class StartListening extends AsyncTask<Void, Void, String> {

    String messageContents;
    AlertAssignments alertAssignments;
    PlaySound soundAlert;
    int counter1;
    int the_alarm;
    int sendAlarm;
    public String the_alarm_S;
    Context contextGUI;
    boolean mBound = false;

    PlaySound mPlaySound;
    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            PlaySound.LocalBinder binder = (PlaySound.LocalBinder) service;
            mPlaySound = binder.getService();
            mBound = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.e("UDP", "Service Disconnected");
            mBound = false;
        }
    };



    public StartListening(Context callerClass) {

        contextGUI = callerClass;
    }


    @Override
    protected void onPreExecute() {

        super.onPreExecute();
        //Intent intent = new Intent(this, PlaySound.class);
        //bindService(intent, mConnection, Context.BIND_AUTO_CREATE);

    }

    @Override
    protected String doInBackground(Void... params)
    {
        int portNumber = 12001;
        DatagramSocket serverSocket;

        try
        {
            serverSocket = new DatagramSocket(portNumber);
            serverSocket.setReuseAddress(true);
            messageContents = "";

            byte[] receiveData = new byte[1024];
            DatagramPacket receivePacket = new DatagramPacket(receiveData, 1024);
            Log.e("UDP", "Waiting for UDP broadcast");
            try
            {
                serverSocket.receive(receivePacket);
                //serverSocket.close();
            }
            catch (IOException e)
            {
                e.printStackTrace();
                return "NA 1!!!1!!!NA 1";
            }
            messageContents = new String( receivePacket.getData() );
            Log.e("UDP", "Received UDP Broadcast with message: " + messageContents);

            serverSocket.close();

            return messageContents;
        }
        catch (SocketException e)
        {
            e.printStackTrace();
            return "NA 2!!!1!!!NA 2";
        }
    }

    TextView mTextView;
    TextView mBlinkView;
    ImageView mImageView;

    @Override
    protected void onPostExecute(String result) {
        // send results from UDP wait back to parent thread
        alertAssignments = new AlertAssignments();
        soundAlert = new PlaySound();


        mImageView = (ImageView) ((MainActivity) contextGUI).findViewById(R.id.image_view);
        mTextView = (TextView) ((MainActivity) contextGUI).findViewById(R.id.alert_text);
        mBlinkView = (TextView) ((MainActivity) contextGUI).findViewById(R.id.blinking_text);
        Animation mAnimation = new AlphaAnimation(0.0f, 1.0f);
        mAnimation.setDuration(50);
        mAnimation.setStartOffset(20);
        mAnimation.setRepeatCount(Animation.INFINITE);
        mAnimation.setRepeatMode(Animation.REVERSE);
        mBlinkView.startAnimation(mAnimation); //animation value

        super.onPostExecute(result);
        the_alarm_S = messageContents;
        String parseMessage[] = the_alarm_S.split("!!!");
        Log.e("UDP", "Parsed message with value " + parseMessage[1]);

        /*if(Integer.valueOf(parseMessage[1]) >= 0 && Integer.valueOf(parseMessage[1]) <= AlertAssignments.alerts.ALERT_ALL_CLEAR.ordinal()) {
            if(sendAlarm == AlertAssignments.alerts.ALERT_ALL_CLEAR.ordinal()) {
                sendAlarm = Integer.valueOf(parseMessage[1]);
                repeatAlarm(sendAlarm);
            }
            else {
                sendAlarm = Integer.valueOf(parseMessage[1]);
                repeatAlarm(sendAlarm);
            }
        }
        */
        Integer parsedMessage = Integer.valueOf(parseMessage[1]);
        mImageView.setImageResource(alertAssignments.alarmImages[parsedMessage]);

        if(parsedMessage >= 10 && parsedMessage <= 19 && parsedMessage != 0) {
            mTextView.setText(alertAssignments.alertTextMessages[parsedMessage]);
        } else {
            mBlinkView.setText(alertAssignments.alertTextMessages[parsedMessage]);
        }
        //soundAlert.playIt(parsedMessage);


    }

}
Stupid question time: am I able to stick this AsyncTask into a Service and have the service run it constantly without clogging up the UI thread? or will I run into the same problem? Instead of dealing with the dumbass's original code I just rewrote the whole thing which took two days so hopefully I'm able to salvage some of that time I spent

edit: I guess this would work? https://gist.github.com/finnjohnsen/3654994

FAT32 SHAMER fucked around with this message at 17:15 on Jul 18, 2017

Volmarias
Dec 31, 2002

EMAIL... THE INTERNET... SEARCH ENGINES...
Without looking at or caring about any of your code, I'd like to point out that you can start a new thread from an Activity, it doesn't actually need to live in a service unless you'd like it to persist when the Activity goes away for some reason.

Create a static class that implements Runnable. Have it's run method check for some member value like isRunning (give it the volatile keyword) and return when false. Have a method that sets isRunning to false, call it in onPause. Pass a Handler reference to your constructor, and pass messages to the handler when you need to update the UI. Create an instance and start a new thread with it in onResume (keep a reference to it so that you can end it in onPause)

Your Handler will update on the UI thread when it receives a message, so update your text fields with whatever.

Refactoring this to be fault tolerant is left as an exercise to the reader.

baka kaba
Jul 19, 2003

PLEASE ASK ME, THE SELF-PROFESSED NO #1 PAUL CATTERMOLE FAN IN THE SOMETHING AWFUL S-CLUB 7 MEGATHREAD, TO NAME A SINGLE SONG BY HIS EXCELLENT NU-METAL SIDE PROJECT, SKUA, AND IF I CAN'T PLEASE TELL ME TO
EAT SHIT

Yeah if you're rewriting it I'd ditch the AsyncTask which is really meant as a quick way to do something off the UI thread and deliver the result on it.

I don't really know much about UDP or preventing car accidents, but it feels like you might want something running in its own thread catching UDP messages and turning them into events to put on a queue to be consumed, which is basically what Volmarias is saying with the 'post messages to the UI thread Handler' pattern

You should probably read this if you haven't already - it talks about what services are and the ways you use them. Briefly the point is to have a component that can run independently of your app (and could even be started by other apps), can manage its own lifetime, and is less likely to be killed by the system when it's low on memory. If you don't care about any of those things, and you just want it to scan for UDPs when the app is in the foreground and stop when it's not, then you don't need to abstract to a service

This covers the whole handler/message thing which is fine for foreground stuff. The CodePath tutorials are generally pretty good!

FAT32 SHAMER
Aug 16, 2012



Volmarias posted:

Without looking at or caring about any of your code, I'd like to point out that you can start a new thread from an Activity, it doesn't actually need to live in a service unless you'd like it to persist when the Activity goes away for some reason.

Create a static class that implements Runnable. Have it's run method check for some member value like isRunning (give it the volatile keyword) and return when false. Have a method that sets isRunning to false, call it in onPause. Pass a Handler reference to your constructor, and pass messages to the handler when you need to update the UI. Create an instance and start a new thread with it in onResume (keep a reference to it so that you can end it in onPause)

Your Handler will update on the UI thread when it receives a message, so update your text fields with whatever.

Refactoring this to be fault tolerant is left as an exercise to the reader.


baka kaba posted:

Yeah if you're rewriting it I'd ditch the AsyncTask which is really meant as a quick way to do something off the UI thread and deliver the result on it.

I don't really know much about UDP or preventing car accidents, but it feels like you might want something running in its own thread catching UDP messages and turning them into events to put on a queue to be consumed, which is basically what Volmarias is saying with the 'post messages to the UI thread Handler' pattern

You should probably read this if you haven't already - it talks about what services are and the ways you use them. Briefly the point is to have a component that can run independently of your app (and could even be started by other apps), can manage its own lifetime, and is less likely to be killed by the system when it's low on memory. If you don't care about any of those things, and you just want it to scan for UDPs when the app is in the foreground and stop when it's not, then you don't need to abstract to a service

This covers the whole handler/message thing which is fine for foreground stuff. The CodePath tutorials are generally pretty good!

oh yeah I guess that's a great point, no need to abstract something like this when I can just have it run on it's own since nothing else will be using it. thanks for the tips and for putting up with my dumbass questions :tipshat:

Volmarias
Dec 31, 2002

EMAIL... THE INTERNET... SEARCH ENGINES...
No problem.

As an aside, is there a reason why you're setting up and tearing down the connection on every button press? Just setting it up once and leaving it open means you can just view the values. Does the broadcast happen too frequently and with enough variance for that to be feasible?

FAT32 SHAMER
Aug 16, 2012



Volmarias posted:

No problem.

As an aside, is there a reason why you're setting up and tearing down the connection on every button press? Just setting it up once and leaving it open means you can just view the values. Does the broadcast happen too frequently and with enough variance for that to be feasible?

That was the idea, the UDP messages are sent every 1/100th of a second and constantly changing due to a vehicle possibly changing position switching a potential alert from standard to imminent. I had it on every button press because the AsyncTask otherwise seems to crash the app when using a Togglebutton + while loop to check if the Togglebutton.isChecked() then running the AsyncTask from that

Previous to your comments I wrote a service to handle the UDP traffic which runs on its own thread, and now that I have it binding it's not receiving the traffic so I'm making sure that i have it pointed at the right ports and all that jazz.

FAT32 SHAMER fucked around with this message at 22:16 on Jul 18, 2017

Adbot
ADBOT LOVES YOU

Scaramouche
Mar 26, 2001

SPACE FACE! SPACE FACE!

I suddenly have a lot less confidence in self-driving car technology....






;)

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply