Interview questions – ANDROID – Receive and manage markers in Google Maps

I recently received negative feedback about testing the interview. They say that they need someone with a higher technical level, the quality of the task was not good enough.

I upload it here to request your knowledge and teach me how I can improve it to improve my development skills in terms of placement of Google Maps and markers.

The verification requirements were:

Call **** and get a grade
(LowerLeftLatLon = 38.711046, -9.160096 & UpperRightLatLon = 38.739429, -9.137115)
This call returns a list of various resources (bicycles, motorcycles,
Bus stops, subway stations, …). Once the call was made, you
must draw all the different resources in GoogleMaps. We are not
need some sofateate at UX level.

What do we want to see

Architecture

endpoint call

Show makers on the map with Google Maps lib. Identify differently
Resources by companyZoneId color

Display the marker information in a new view

Extra: If the user moves on the map, update the pois

Here is the paste of my main job:

class MapsActivity : AppCompatActivity(), OnMapReadyCallback {

    private lateinit var mMap: GoogleMap
    private var disposableCall: Disposable? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_maps)

        // Obtain the SupportMapFragment and get notified when the map is ready to be used.
        val mapFragment = supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment
        mapFragment.getMapAsync(this)
    }


    /** when map is ready, we can set:
     *  starting bounds
     *  request Pois (MapResources)
     *  set map clicks and infowindow*/
    override fun onMapReady(googleMap: GoogleMap) {
        mMap = googleMap

        val startBounds = LatLngBounds(
            LatLng(38.711046, -9.160096),
            LatLng(38.739429, -9.137115)
        )

        mMap.setOnMapLoadedCallback {
            mMap.animateCamera(CameraUpdateFactory.newLatLngBounds(startBounds, 17))
        }

        /**EXTRA, unlock to update POIs when user change map bounds, but with requestResource, it can cause stress
         * it can be optimized with feats like:
         * - Don't redraw existing POIS
         * - If zoom out, group nearer POIS into one
         * - Delete POIS out of view
         * */
        /* mMap.setOnCameraChangeListener {
             it as CameraPosition
             requestResources(mMap.projection.visibleRegion.latLngBounds)
         }*/

        mMap.setInfoWindowAdapter(
            InfoWindowCustom(this)
        )

        mMap.setOnInfoWindowClickListener {
            Toast.makeText(this, "wi!", Toast.LENGTH_SHORT).show()
            try {
                startActivity(
                    ResourceDetailActivity.newInstance(this@MapsActivity, it.snippet)
                )
            } catch (e: Exception) {
                Log.e("MAP", e.localizedMessage)
            }
        }
        requestResources(startBounds)
    }

    /**
     * Async call(RX) to get resources
     * if call is in progress (!disposed) we dispose it before create a new call
     */
    private fun requestResources(bounds: LatLngBounds) {

        disposableCall?.apply {
            if (!this.isDisposed) dispose()
        }

        disposableCall = NetRepo().getMapResources(bounds.northeast, bounds.southwest)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribeBy(
                onNext = { listOfResults ->
                    addResourcesFromList(listOfResults)
                },
                onError = {
                    Log.e("DisposeCall", "ERROR: ${it.localizedMessage}")
                }
            )
    }

    /** call addMarker function for each item of received list*/
    private fun addResourcesFromList(listOfResults: List) {
        for (item in listOfResults) {
            if (!existInMap(item)) {
                addMarker(item)
            }
        }
    }

    /** returns if item is already present in the markers*/
    private fun existInMap(item: MapResource): Boolean {
        //TODO check if item is present in map, if it's present, it should not be repainted
        // we can manage this with marker hashmap, if it return the marker requested, it exists in the map
        return false
    }

    /** returns one BitmapDescriptor containing the marker icon tinted as param color*/
    private fun getTintedMarker(color: Int): BitmapDescriptor? {
        val markerBitmap =
            BitmapFactory.decodeResource(
                resources,
                R.drawable.baseline_place_white_24
            )
        val resultBitmap = Bitmap.createBitmap(
            markerBitmap,
            0,
            0,
            markerBitmap.width - 1,
            markerBitmap.height - 1
        )
        val filter: ColorFilter = PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN)

        val markerPaint = Paint()
        markerPaint.colorFilter = filter

        val canvas = Canvas(resultBitmap)
        canvas.drawBitmap(resultBitmap, 0f, 0f, markerPaint)
        return BitmapDescriptorFactory.fromBitmap(resultBitmap)
    }

    /** returns one color for each different companyZoneId
     * it passes the value from 3 digits to 6 according:
     * colorValue = abc
     * newColorValue = aabbcc
     * to use it as parseable color
     * */
    private fun colorOfItem(item: MapResource): Int {
        return item.companyZoneId?.let {
            var colorString = "#${item.companyZoneId}"

            colorString =
                colorString.replace(
                    "#((0-9a-fA-F))((0-9a-fA-F))((0-9a-fA-F))".toRegex(),
                    "#$1$1$2$2$3$3"
                )
            Color.parseColor(colorString)
        } ?: run { 0 }
    }

    /** Adds the marker to the map*/
    private fun addMarker(item: MapResource) {

        val coordinates = LatLng(item.lat!!, item.lon!!)

        mMap.addMarker(
            MarkerOptions()
                .icon(getTintedMarker(colorOfItem(item)))
                .position(coordinates)
                .infoWindowAnchor(0.5f, -0.1f)
                .snippet(Gson().toJson(item))
        )

    }
}

The InfoView too:

class InfoWindowCustom(var context: Context) : InfoWindowAdapter {
    var inflater: LayoutInflater? = null

    override fun getInfoContents(marker: Marker): View? {
        inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
        val v = inflater!!.inflate(R.layout.view_mapinfoview, null)
        val llInfoWindow = v.findViewById(R.id.llInfoWindow) as LinearLayout

        Gson().fromJson(marker.snippet, MapResource::class.java)?.let {
            paintData(context, llInfoWindow, it)
            addOnClickInfo(llInfoWindow)
        }
        return v
    }

    private fun addOnClickInfo(llInfoWindow: LinearLayout) {
        val infoText = TextView(context)
        infoText.text = "Click me for more detail"
        infoText.setTextColor(Color.BLUE)
        infoText.setPadding(5, 5, 5, 5)
        llInfoWindow.addView(infoText)
    }

    override fun getInfoWindow(marker: Marker): View? {
        return null
    }
}

And the map resource object:

class MapResource {
    @SerializedName("id")
    @Expose
    var id: String? = null

    @SerializedName("name")
    @Expose
    var name: String? = null

    @SerializedName("scheduledArrival")
    @Expose
    var scheduledArrival: Int? = null

    @SerializedName("locationType")
    @Expose
    var locationType: Int? = null

    @SerializedName("companyZoneId")
    @Expose
    var companyZoneId: Int? = null

    @SerializedName("lat", alternate = ("y"))
    @Expose
    var lat: Double? = null

    @SerializedName("lon", alternate = ("x"))
    @Expose
    var lon: Double? = null

    @SerializedName("licencePlate")
    @Expose
    var licencePlate: String? = null

    @SerializedName("range")
    @Expose
    var range: Int? = null

    @SerializedName("batteryLevel")
    @Expose
    var batteryLevel: Int? = null

    @SerializedName("seats")
    @Expose
    var seats: Int? = null

    @SerializedName("model")
    @Expose
    var model: String? = null

    @SerializedName("resourceImageId")
    @Expose
    var resourceImageId: String? = null

    @SerializedName("pricePerMinuteParking")
    @Expose
    var pricePerMinuteParking: Double? = null

    @SerializedName("pricePerMinuteDriving")
    @Expose
    var pricePerMinuteDriving: Double? = null

    @SerializedName("realTimeData")
    @Expose
    var realTimeData: Boolean? = null

    @SerializedName("engineType")
    @Expose
    var engineType: String? = null

    @SerializedName("resourceType")
    @Expose
    var resourceType: String? = null

    @SerializedName("helmets")
    @Expose
    var helmets: Int? = null

    @SerializedName("station")
    @Expose
    var station: Boolean? = null

    @SerializedName("availableResources")
    @Expose
    var availableResources: Int? = null

    @SerializedName("spacesAvailable")
    @Expose
    var spacesAvailable: Int? = null

    @SerializedName("allowDropoff")
    @Expose
    var allowDropoff: Boolean? = null

    @SerializedName("bikesAvailable")
    @Expose
    var bikesAvailable: Int? = null
}

The full code of the task can be found here.

Also in the ws package I added a text with the sample answer of the demo coordinates.

Any help to improve this would be great even after you lose this job.

After a year, does the person who rejected you on Facebook receive a notification on Facebook that the person who rejected you can now add them again?

Someone I know I sent a friend request like a year ago and they declined. A year has passed since then and I still can't send her a friend request, but on one of my other accounts I can still add her to the account. Does this mean they'll be notified that it's been a year since they rejected you, and they can now send you another friend request and post it where I still can't add it?

Sharepoint Server – I would like to receive a list in which Invoice _Category is Service. Please help.

Try to use your CAML in the following format:


    
        
            
                
                Service
            
        
    

Note::

  1. You must use the internal name of your column / field in the CAML query.

    Find the internal name of the SharePoint column

Complete code::

string siteUrl = "http://tenant.sharepoint.com/sites/SiteName";  

ClientContext clientContext = new ClientContext(siteUrl);  
SP.List oList = clientContext.Web.Lists.GetByTitle("ListName");  

CamlQuery camlQuery = new CamlQuery();  
camlQuery.ViewXml = "Service";  

ListItemCollection collListItem = oList.GetItems(camlQuery);  

clientContext.Load(collListItem);  
clientContext.ExecuteQuery();  

foreach (ListItem oListItem in collListItem) {  
    Console.WriteLine("ID: {0} nTitle: {1}", oListItem.Id, oListItem("Title"));  
}  

The device does not receive a network address from AirPort Extreme

I have a 3TB Time Capsule that is connected to the pace cable modem and that provides internet access.

I have a Popcorn Hour and NMT – Network Media Tank device that only has a wired internet connection that is physically difficult to reach with a Cat 6 cable. My solution was to use an Airport Extreme that was configured to expand a "wireless" network.

The problem I am having is that the NMT is not getting an IP address on the 192 network. It shows a 169 address. I tested the device that is physically attached to the 3 TB Time Capsule and it got a 192 address.

So my question is why the Airport Extreme doesn't assign a 192 address for the cable connection.

By the way: A netstat command to display the routing table did not show the device at address 169.

Payment – Receive money for the first time

All you need to get money is a valid bitcoin address. To create a Bitcoin address, users generally use software that is able to generate the cryptographic keys from which the Bitcoin address is derived.

In the simplest case, all you have to do is download Bitcoin wallet software, which will then provide you with a Bitcoin address to which you can get money. All you have to do is copy this address and send it to the person you want to pay for.

Note that you should send a new receiving address for every payment (every good wallet will automatically give you a new address each time you make a payment. This is very important to your privacy (and the privacy of those you use to process transactions).

Do I have to do a transaction with an existing account before I receive payments to confirm my account?

Absolutely not.

namecoin – (ncdns) Tries to resolve the .bit domain using the dig command, but does not receive an answer

I am trying to resolve the namecoin domain easyminer.bit with ncdns.
The domain is active:

{
    "name": "d/easyminer",
    "name_encoding": "utf8",
    "value": "{onehundrednmcpername@protonmail.com}",
    "value_encoding": "ascii",
    "txid": "23fa46110ab90ba654613774c2c01eb524ab300c3863623b3e6a9388cd479fad",
    "vout": 1,
    "address": "NDxY6mrSYdsTsEYRmA1SNFptW6GCsjuAps",
    "height": 474143,
    "expires_in": 18649,
    "expired": false,
    "ismine": false
  },

When I use the command dig @127.0.0.1 -p 1025 easyminer.bit NS However, I don't get any answers back, just:

; <<>> DiG 9.14.9 <<>> @127.0.0.1 -p 1025 easyminer.bit NS
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 21680
;; flags: qr aa rd; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
; COOKIE: 080dbfec01213f1c (echoed)
;; QUESTION SECTION:
;easyminer.bit.                 IN      NS

;; Query time: 1514 msec
;; SERVER: 127.0.0.1#1025(127.0.0.1)
;; WHEN: Fri Jan 31 01:07:40 Mitteleuropõische Zeit 2020
;; MSG SIZE  rcvd: 54

If I have the domain & # 39; jamieweb.bit & # 39; or & # 39; nf.bit & # 39; I get an A Resource Record with the IP address back.

Can someone tell me where the problem seems to be?

Thank you in advance.

Best regards