Git Product home page Git Product logo

hossain-khan / android-police-brutality-incidents Goto Github PK

View Code? Open in Web Editor NEW
5.0 1.0 1.0 69.54 MB

2020PB Android client app for https://github.com/2020PB/police-brutality (Repository containing evidence of police brutality during the 2020 George Floyd protests)

Home Page: https://github.com/2020PB/police-brutality

License: MIT License

Kotlin 93.35% Groovy 0.92% Java 2.52% HTML 3.20%
black-lives-matter police-brutality android android-application 2020pb blacklivesmatter

android-police-brutality-incidents's Introduction

Hi there πŸ‘‹

It's Hossain. A 🍱 foodie, ⛰️ traveler, πŸ“Έ snapper, and πŸ‘¨β€πŸ’» developer by day.

android-police-brutality-incidents's People

Contributors

hossain-khan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

android-police-brutality-incidents's Issues

Design link preview UI for each incident

Come up with a UI strategy to render links from different media.

Example snapshot of data https://github.com/amardeshbd/android-police-brutality-incidents/blob/develop/resources/api-data-snapshot/all-locations-2020.06.06-08am.json

Sample URLs

Dynamically adding views to flow didn't work

Based on some research (https://stackoverflow.com/questions/59084494/how-can-we-add-views-dynamically-androidx-constraintlayout-helper-widget-flow-an), the solution didn't work

            <com.google.android.material.textview.MaterialTextView
                android:id="@+id/incident_title"
                style="@style/TextAppearance.MaterialComponents.Body1"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:padding="16dp"
                android:text="@{incident.name}"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent"
                tools:text="Item Description" />

            <com.google.android.material.textview.MaterialTextView
                android:id="@+id/incident_links_label"
                style="@style/TextAppearance.MaterialComponents.Caption"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:text="Resources"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/incident_title" />

            <androidx.constraintlayout.helper.widget.Flow
                android:id="@+id/links_flow"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:padding="10dp"
                app:constraint_referenced_ids="button"
                app:flow_horizontalBias="0"
                app:flow_horizontalGap="10dp"
                app:flow_horizontalStyle="packed"
                app:flow_verticalBias="0"
                app:flow_wrapMode="chain"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/incident_links_label" />

            <com.google.android.material.button.MaterialButton
                android:id="@+id/button"
                style="@style/Widget.MaterialComponents.Button.TextButton.Icon"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="This is a text button"
                app:icon="@drawable/ic_outline_web_24"
                tools:ignore="MissingConstraints" />

and

        item.links.forEach {
            Timber.d("Adding dynamic view for link: $it")
            val button = MaterialButton(binding.root.context, null, R.attr.borderlessButtonStyle)
            val generateViewId = View.generateViewId()
            button.id = generateViewId
            button.text = it
            binding.container.addView(button)
            binding.linksFlow.addView(button)
            binding.linksFlow.referencedIds = binding.linksFlow.referencedIds.plus(generateViewId)
        }

May be investigate later, for now use recycler view to keep it simple.

Incident details page with evidence?

As an enhanced version, maybe details view can be provided for each incident based on API data.

Sample response with evidence - https://api.846policebrutality.com/api/incidents/5e4b6c50-abf9-11ea-9699-279bedb1b82e?include=evidence

{
   "data":[
      {
         "id":"5e4b6c50-abf9-11ea-9699-279bedb1b82e",
         "pb_id":"pa-pittsburgh-2",
         "state":"Pennsylvania",
         "city":"Pittsburgh",
         "date":"2020-06-01T00:00:00.000000Z",
         "title":"Police fire tear gas and rubber bullets on peaceful assembly",
         "description":null,
         "links":[
            "https:\/\/www.reddit.com\/r\/pittsburgh\/comments\/guzshz\/police_declaring_an_unlawful_assembly_against_a\/",
            "https:\/\/www.facebook.com\/BenjaminKFerris\/posts\/3091613010894973",
            "https:\/\/twitter.com\/gautamyadav818\/status\/1267606317893550080"
         ],
         "data":null,
         "geocoding":{
            "lat":"40.4406248",
            "long":"-79.9958864"
         },
         "evidence":[
            {
               "id":"5e4b8bf0-abf9-11ea-820b-a915e35341e1",
               "incident_id":"5e4b6c50-abf9-11ea-9699-279bedb1b82e",
               "url":"https:\/\/www.reddit.com\/r\/pittsburgh\/comments\/guzshz\/police_declaring_an_unlawful_assembly_against_a\/",
               "video_status":"ok",
               "created_at":"2020-06-11T15:36:50.000000Z",
               "updated_at":"2020-06-11T15:38:00.000000Z",
               "video":[
                  {
                     "id":"1861a870-a873-11ea-9be8-7d2331b735fa",
                     "evidence_url":"https:\/\/www.reddit.com\/r\/pittsburgh\/comments\/guzshz\/police_declaring_an_unlawful_assembly_against_a\/",
                     "title":"Police declaring an unlawful assembly against a peaceful protest. Escalating the situation for no reason. From today",
                     "description":null,
                     "site":"Reddit",
                     "url":"https:\/\/www.reddit.com\/r\/pittsburgh\/comments\/guzshz\/police_declaring_an_unlawful_assembly_against_a\/",
                     "duration":"0.00",
                     "tags":[

                     ],
                     "thumbnail":null,
                     "streams":[
                        {
                           "url":"https:\/\/v.redd.it\/udseo7e74f251\/DASH_1080",
                           "format":"dash-VIDEO-1 - 608x1080",
                           "format_note":"video only, no audio",
                           "extension":"mp4",
                           "video_codec":"avc1.4d4028",
                           "audio_codec":"none",
                           "height":1080,
                           "width":608,
                           "fps":30,
                           "fmt_id":"dash-VIDEO-1",
                           "filesize":null,
                           "filesize_pretty":"-",
                           "has_audio":false,
                           "has_video":true,
                           "is_hd":false
                        },
                        {
                           "url":"https:\/\/v.redd.it\/udseo7e74f251\/DASH_720",
                           "format":"dash-VIDEO-2 - 404x720",
                           "format_note":"video only, no audio",
                           "extension":"mp4",
                           "video_codec":"avc1.4d401f",
                           "audio_codec":"none",
                           "height":720,
                           "width":404,
                           "fps":30,
                           "fmt_id":"dash-VIDEO-2",
                           "filesize":null,
                           "filesize_pretty":"-",
                           "has_audio":false,
                           "has_video":true,
                           "is_hd":false
                        },
                        {
                           "url":"https:\/\/v.redd.it\/udseo7e74f251\/DASH_480",
                           "format":"dash-VIDEO-3 - 270x480",
                           "format_note":"video only, no audio",
                           "extension":"mp4",
                           "video_codec":"avc1.4d401f",
                           "audio_codec":"none",
                           "height":480,
                           "width":270,
                           "fps":30,
                           "fmt_id":"dash-VIDEO-3",
                           "filesize":null,
                           "filesize_pretty":"-",
                           "has_audio":false,
                           "has_video":true,
                           "is_hd":false
                        },
                        {
                           "url":"https:\/\/v.redd.it\/udseo7e74f251\/DASH_360",
                           "format":"dash-VIDEO-4 - 202x360",
                           "format_note":"video only, no audio",
                           "extension":"mp4",
                           "video_codec":"avc1.4d401e",
                           "audio_codec":"none",
                           "height":360,
                           "width":202,
                           "fps":30,
                           "fmt_id":"dash-VIDEO-4",
                           "filesize":null,
                           "filesize_pretty":"-",
                           "has_audio":false,
                           "has_video":true,
                           "is_hd":false
                        },
                        {
                           "url":"https:\/\/v.redd.it\/udseo7e74f251\/DASH_240",
                           "format":"dash-VIDEO-5 - 134x240",
                           "format_note":"video only, no audio",
                           "extension":"mp4",
                           "video_codec":"avc1.4d401e",
                           "audio_codec":"none",
                           "height":240,
                           "width":134,
                           "fps":30,
                           "fmt_id":"dash-VIDEO-5",
                           "filesize":null,
                           "filesize_pretty":"-",
                           "has_audio":false,
                           "has_video":true,
                           "is_hd":false
                        },
                        {
                           "url":"https:\/\/v.redd.it\/udseo7e74f251\/DASH_96",
                           "format":"dash-VIDEO-6 - 54x96",
                           "format_note":"video only, no audio",
                           "extension":"mp4",
                           "video_codec":"avc1.4d400d",
                           "audio_codec":"none",
                           "height":96,
                           "width":54,
                           "fps":30,
                           "fmt_id":"dash-VIDEO-6",
                           "filesize":null,
                           "filesize_pretty":"-",
                           "has_audio":false,
                           "has_video":true,
                           "is_hd":false
                        },
                        {
                           "url":"https:\/\/v.redd.it\/udseo7e74f251\/audio",
                           "format":"dash-AUDIO-1 - audio only",
                           "format_note":"audio only, no video",
                           "extension":"m4a",
                           "video_codec":"none",
                           "audio_codec":"mp4a.40.2",
                           "height":null,
                           "width":null,
                           "fps":null,
                           "fmt_id":"dash-AUDIO-1",
                           "filesize":null,
                           "filesize_pretty":"-",
                           "has_audio":true,
                           "has_video":false,
                           "is_hd":false
                        }
                     ],
                     "created_at":"2020-06-07T03:58:07.000000Z",
                     "updated_at":"2020-06-07T03:58:07.000000Z"
                  }
               ]
            },
            {
               "id":"5e4baab0-abf9-11ea-89ca-b52ef1400108",
               "incident_id":"5e4b6c50-abf9-11ea-9699-279bedb1b82e",
               "url":"https:\/\/www.facebook.com\/BenjaminKFerris\/posts\/3091613010894973",
               "video_status":"ok",
               "created_at":"2020-06-11T15:36:50.000000Z",
               "updated_at":"2020-06-11T15:38:00.000000Z",
               "video":[
                  {
                     "id":"1a19f1b0-a873-11ea-b27a-d992aadca1f8",
                     "evidence_url":"https:\/\/www.facebook.com\/BenjaminKFerris\/posts\/3091613010894973",
                     "title":"This is not a riot.",
                     "description":null,
                     "site":"Facebook",
                     "url":"https:\/\/www.facebook.com\/BenjaminKFerris\/posts\/3091613010894973",
                     "duration":"0.00",
                     "tags":[

                     ],
                     "thumbnail":"https:\/\/scontent-dus1-1.xx.fbcdn.net\/v\/t15.5256-10\/100802547_3091613724228235_1198368705344438272_n.jpg?_nc_cat=111&_nc_sid=f2c4d5&_nc_ohc=rzvyI4mdQoAAX9gBx_a&_nc_ht=scontent-dus1-1.xx&oh=51e6bec27d1fa2a699a208e4bdff6e84&oe=5F009910",
                     "streams":[
                        {
                           "url":"https:\/\/video-dus1-1.xx.fbcdn.net\/v\/t42.9040-2\/101682724_617705055762700_6686501323745001472_n.mp4?_nc_cat=103&_nc_sid=985c63&efg=eyJybHIiOjk3MywicmxhIjo1MTIsInZlbmNvZGVfdGFnIjoic3ZlX3NkIn0%3D&_nc_ohc=5_UYJLeuT_sAX_Jb3uL&rl=973&vabr=541&_nc_ht=video-dus1-1.xx&oh=bfc5164e8f18a986c53bba2fc7b7ed4c&oe=5EDC856C",
                           "format":"dash_sd_src - unknown",
                           "format_note":"",
                           "extension":"mp4",
                           "fmt_id":"dash_sd_src",
                           "filesize":null,
                           "filesize_pretty":"-",
                           "has_audio":true,
                           "has_video":true,
                           "is_hd":false
                        },
                        {
                           "url":"https:\/\/video-dus1-1.xx.fbcdn.net\/v\/t42.9040-2\/101682724_617705055762700_6686501323745001472_n.mp4?_nc_cat=103&_nc_sid=985c63&efg=eyJ2ZW5jb2RlX3RhZyI6InN2ZV9zZCJ9&_nc_ohc=5_UYJLeuT_sAX_Jb3uL&_nc_ht=video-dus1-1.xx&oh=bfc5164e8f18a986c53bba2fc7b7ed4c&oe=5EDC856C",
                           "format":"dash_sd_src_no_ratelimit - unknown",
                           "format_note":"",
                           "extension":"mp4",
                           "fmt_id":"dash_sd_src_no_ratelimit",
                           "filesize":null,
                           "filesize_pretty":"-",
                           "has_audio":true,
                           "has_video":true,
                           "is_hd":false
                        },
                        {
                           "url":"https:\/\/video-dus1-1.xx.fbcdn.net\/v\/t39.24130-2\/10000000_3498986686796581_8918889357952987812_n.mp4?_nc_cat=100&_nc_sid=985c63&efg=eyJ2ZW5jb2RlX3RhZyI6Im9lcF9oZCJ9&_nc_ohc=1Ko0BH3HEKwAX9hL0oI&_nc_ht=video-dus1-1.xx&oh=b1d6ca78d4686cf1079cba44d7590f60&oe=5F006609",
                           "format":"dash_hd_src - unknown",
                           "format_note":"",
                           "extension":"mp4",
                           "fmt_id":"dash_hd_src",
                           "filesize":null,
                           "filesize_pretty":"-",
                           "has_audio":true,
                           "has_video":true,
                           "is_hd":false
                        },
                        {
                           "url":"https:\/\/video-dus1-1.xx.fbcdn.net\/v\/t39.25447-2\/10000000_3129018620521801_2923794735394972715_n.mp4?_nc_cat=109&_nc_sid=5aebc0&efg=eyJ2ZW5jb2RlX3RhZyI6ImRhc2hfb2VwX2hxMl9mcmFnXzJfdmlkZW8ifQ==&_nc_ohc=8cZTCWLFMr0AX-PGusR&_nc_ht=video-dus1-1.xx&oh=0432d3172765fbe763f2268aae3e3623&oe=5F01BACD",
                           "format":"v - 1280x720",
                           "format_note":"video only, no audio",
                           "extension":"mp4",
                           "video_codec":"avc1.4D401F",
                           "audio_codec":"none",
                           "height":720,
                           "width":1280,
                           "fps":null,
                           "fmt_id":"873736379797897v",
                           "filesize":null,
                           "filesize_pretty":"-",
                           "has_audio":false,
                           "has_video":true,
                           "is_hd":false
                        },
                        {
                           "url":"https:\/\/video-dus1-1.xx.fbcdn.net\/v\/t39.25447-2\/10000000_149438613305597_9068834334226225958_n.mp4?_nc_cat=100&_nc_sid=5aebc0&efg=eyJ2ZW5jb2RlX3RhZyI6ImRhc2hfb2VwX2hxNF9mcmFnXzJfdmlkZW8ifQ==&_nc_ohc=HWRf__RjEQ4AX8KL_qC&_nc_ht=video-dus1-1.xx&oh=5b077c044ddba587512df3c328d6c203&oe=5F012E86",
                           "format":"v - 852x480",
                           "format_note":"video only, no audio",
                           "extension":"mp4",
                           "video_codec":"avc1.4D401F",
                           "audio_codec":"none",
                           "height":480,
                           "width":852,
                           "fps":null,
                           "fmt_id":"1713731935449963v",
                           "filesize":null,
                           "filesize_pretty":"-",
                           "has_audio":false,
                           "has_video":true,
                           "is_hd":false
                        },
                        {
                           "url":"https:\/\/video-dus1-1.xx.fbcdn.net\/v\/t39.25447-2\/100998527_112307810332082_6260778437459121279_n.mp4?_nc_cat=101&_nc_sid=5aebc0&efg=eyJ2ZW5jb2RlX3RhZyI6ImRhc2hfb2VwX2hxMV9mcmFnXzJfdmlkZW8ifQ==&_nc_ohc=Q8DzqxRTXV8AX_XsuS2&_nc_ht=video-dus1-1.xx&oh=2c14028d990996ecfd099d5c39e69b6c&oe=5F01387C",
                           "format":"v - 640x360",
                           "format_note":"video only, no audio",
                           "extension":"mp4",
                           "video_codec":"avc1.4D401E",
                           "audio_codec":"none",
                           "height":360,
                           "width":640,
                           "fps":null,
                           "fmt_id":"1704340183049691v",
                           "filesize":null,
                           "filesize_pretty":"-",
                           "has_audio":false,
                           "has_video":true,
                           "is_hd":false
                        },
                        {
                           "url":"https:\/\/video-dus1-1.xx.fbcdn.net\/v\/t39.25447-2\/100409710_590959094859220_1628372651185974532_n.mp4?_nc_cat=103&_nc_sid=5aebc0&efg=eyJ2ZW5jb2RlX3RhZyI6ImRhc2hfb2VwX2xxMV9mcmFnXzJfdmlkZW8ifQ==&_nc_ohc=zBPsMD-3I60AX8sHqUq&_nc_ht=video-dus1-1.xx&oh=97f75d0fd3932c5e5f3cbe87cccda518&oe=5F033B56",
                           "format":"v - 426x240",
                           "format_note":"video only, no audio",
                           "extension":"mp4",
                           "video_codec":"avc1.4D401E",
                           "audio_codec":"none",
                           "height":240,
                           "width":426,
                           "fps":null,
                           "fmt_id":"284927682661977v",
                           "filesize":null,
                           "filesize_pretty":"-",
                           "has_audio":false,
                           "has_video":true,
                           "is_hd":false
                        },
                        {
                           "url":"https:\/\/video-dus1-1.xx.fbcdn.net\/v\/t39.25447-2\/100442904_2318252338477875_1194406806440393725_n.mp4?_nc_cat=103&_nc_sid=5aebc0&efg=eyJ2ZW5jb2RlX3RhZyI6ImRhc2hfb2VwX2xxMl9mcmFnXzJfdmlkZW8ifQ==&_nc_ohc=PqpkgzmmKbUAX8isEbQ&_nc_ht=video-dus1-1.xx&oh=c6ad330e32e3a0ff21133a09759ce0ad&oe=5F01671A",
                           "format":"v - 256x144",
                           "format_note":"video only, no audio",
                           "extension":"mp4",
                           "video_codec":"avc1.4D401E",
                           "audio_codec":"none",
                           "height":144,
                           "width":256,
                           "fps":null,
                           "fmt_id":"183260119684202v",
                           "filesize":null,
                           "filesize_pretty":"-",
                           "has_audio":false,
                           "has_video":true,
                           "is_hd":false
                        },
                        {
                           "url":"https:\/\/video-dus1-1.xx.fbcdn.net\/v\/t42.1790-2\/102829066_256888012051362_8010641321649766400_n.mp4?_nc_cat=111&_nc_sid=5aebc0&efg=eyJ2ZW5jb2RlX3RhZyI6ImRhc2hfdjRhdWRpb2ZvcnNvdXJjZXBpcGVsaW5lXzEyOF9jcmZfMjNfbWFpbl8zLjBfZnJhZ18yX2F1ZGlvIn0=&_nc_ohc=gwby5A78Ei0AX9hlt1b&_nc_ht=video-dus1-1.xx&oh=fc95d8e7a335760ee6ba5dcfe5aefd2e&oe=5EDC8EA4",
                           "format":"a - audio only",
                           "format_note":"audio only, no video",
                           "extension":"m4a",
                           "video_codec":"none",
                           "audio_codec":"mp4a.40.5",
                           "height":null,
                           "width":null,
                           "fps":null,
                           "fmt_id":"256888005384696a",
                           "filesize":null,
                           "filesize_pretty":"-",
                           "has_audio":true,
                           "has_video":false,
                           "is_hd":false
                        }
                     ],
                     "created_at":"2020-06-07T03:58:10.000000Z",
                     "updated_at":"2020-06-07T03:58:10.000000Z"
                  }
               ]
            },
            {
               "id":"5e4bc6a0-abf9-11ea-957f-8d5b5f6e1619",
               "incident_id":"5e4b6c50-abf9-11ea-9699-279bedb1b82e",
               "url":"https:\/\/twitter.com\/gautamyadav818\/status\/1267606317893550080",
               "video_status":"ok",
               "created_at":"2020-06-11T15:36:50.000000Z",
               "updated_at":"2020-06-11T15:38:00.000000Z",
               "video":[
                  {
                     "id":"1b7ddd00-a873-11ea-991e-f12458a61b73",
                     "evidence_url":"https:\/\/twitter.com\/gautamyadav818\/status\/1267606317893550080",
                     "title":"Gautam Yadav? - Protestors were chanting when the police came and started throwing tear gas. Not sure what made them do that. East Liberty #PittsburghProtest.",
                     "description":"Protestors were chanting when the police came and started throwing tear gas. Not sure what made them do that. East Liberty #PittsburghProtest. https:\/\/t.co\/qmSxYdV9ep",
                     "site":"Twitter",
                     "url":"https:\/\/twitter.com\/gautamyadav818\/status\/1267606317893550080",
                     "duration":"108.37",
                     "tags":[
                        "PittsburghProtest"
                     ],
                     "thumbnail":"https:\/\/pbs.twimg.com\/ext_tw_video_thumb\/1267606125001793546\/pu\/img\/rrN59ShEKIsdHR6L.jpg?name=orig",
                     "streams":[
                        {
                           "url":"https:\/\/video.twimg.com\/ext_tw_video\/1267606125001793546\/pu\/vid\/960x544\/286k_WUhDJFWJ-O1.mp4?tag=10",
                           "format":"http-2176 - 960x544",
                           "format_note":"",
                           "extension":"mp4",
                           "height":544,
                           "width":960,
                           "fmt_id":"http-2176",
                           "filesize":null,
                           "filesize_pretty":"-",
                           "has_audio":true,
                           "has_video":true,
                           "is_hd":false
                        },
                        {
                           "url":"https:\/\/video.twimg.com\/ext_tw_video\/1267606125001793546\/pu\/vid\/634x360\/KhqdGYs6baUOo92J.mp4?tag=10",
                           "format":"http-832 - 634x360",
                           "format_note":"",
                           "extension":"mp4",
                           "height":360,
                           "width":634,
                           "fmt_id":"http-832",
                           "filesize":null,
                           "filesize_pretty":"-",
                           "has_audio":true,
                           "has_video":true,
                           "is_hd":false
                        },
                        {
                           "url":"https:\/\/video.twimg.com\/ext_tw_video\/1267606125001793546\/pu\/vid\/476x270\/ToJ49gJwcXDycXTC.mp4?tag=10",
                           "format":"http-256 - 476x270",
                           "format_note":"",
                           "extension":"mp4",
                           "height":270,
                           "width":476,
                           "fmt_id":"http-256",
                           "filesize":null,
                           "filesize_pretty":"-",
                           "has_audio":true,
                           "has_video":true,
                           "is_hd":false
                        }
                     ],
                     "created_at":"2020-06-07T03:58:12.000000Z",
                     "updated_at":"2020-06-07T03:58:12.000000Z"
                  }
               ]
            }
         ]
      }
   ],
   "meta":{
      "about":[
         "8 minutes and 46 seconds is the length of time associated with the killing of George Floyd,",
         "who died in police custody after police officer Derek Chauvin knelt on his neck for roughly eight minutes.",
         "This repo provides and API and archives acts of assault by public servants to American Citizens during non-violent acts of protest."
      ],
      "more":[
         "\u2022 This project does not condone acts aggression of any parties",
         "\u2022 This project is meant to enable others to share their voice and stand-up against acts of violence by public servants",
         "\u2022 This project intends to fight censorship by encouraging all to get involved and mirror this data, download the media, and fight for progress",
         "\u2022 This project is not anti-police",
         "\u2022 This project is a public work dedicated to all of humanity, regardless of race, creed, or borders."
      ],
      "get_involved":{
         "reddit":"https:\/\/www.reddit.com\/r\/2020PoliceBrutality\/",
         "collaboration":"https:\/\/github.com\/2020PB\/police-brutality"
      }
   }
}

More info on sate list view

Is your feature request related to a problem? Please describe.
On location list, we can have another line saying Most recent incident on DATE

or - X days ago on Jul 5th

Google Play app publish - delay and review feedback from Google Play Developer Support

Just submitted support request

I have submitted a brand new app with Application ID: "com.blacklivesmatter.policebrutality"

The application was originally submitted on June 8th 2020 and published v1.5 to production
and later on June 18th 2020 published v2.1 to production.

I am aware of the following notice in Google Play console and understand the cause:
> "We're experiencing longer than usual review times"
> "Due to adjusted work schedules at this time, you may experience longer than usual review times for your app."

However, I was wondering if there is any way I can help to expedite the review process. Thank you.

Regards,
Hossain

Developer account ID
5828904355739995413

Use proguard, enabled R8

Optimize for release builds.

Current

        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.config
        }

How to deal with stale data from local database?

Currently the app caches data locally. It does do API sync, but only update or adds it. Not delete.

Idea, may be it can have a work manager worker to do late-night sync to delete stale data. πŸ€”

Add map view for items that has location.

Is your feature request related to a problem? Please describe.
When user taps on an item, we can have a map view.

  • Add a placeholder while the map is being loaded.
  • Add dark mode style for the map view.
  • Add a drwable right map icon if the item has valid coordinates

Additional context
Sample data from data snapshot

geocoding | Β 
-- | --
lat | "38.9071923"
long | "-77.0368707"

Possible memory leak

┬───
β”‚ GC Root: Local variable in native code
β”‚
β”œβ”€ com.google.android.gms.measurement.internal.zzfz instance
β”‚    Leaking: NO (MainActivity↓ is not leaking)
β”‚    Thread name: 'Measurement Worker'
β”‚    ↓ zzfz.zzd
β”œβ”€ com.google.android.gms.measurement.internal.zzfv instance
β”‚    Leaking: NO (MainActivity↓ is not leaking)
β”‚    ↓ zzfv.zzy
β”œβ”€ com.google.android.gms.measurement.internal.zzfy instance
β”‚    Leaking: NO (MainActivity↓ is not leaking)
β”‚    ↓ zzfy.zzq
β”œβ”€ com.google.android.gms.measurement.internal.zzii instance
β”‚    Leaking: NO (MainActivity↓ is not leaking)
β”‚    ↓ zzii.zze
β”œβ”€ com.blacklivesmatter.policebrutality.MainActivity instance
β”‚    Leaking: NO (NavHostFragment↓ is not leaking and Activity#mDestroyed is false)
β”‚    ↓ MainActivity.mFragments
β”œβ”€ androidx.fragment.app.FragmentController instance
β”‚    Leaking: NO (NavHostFragment↓ is not leaking)
β”‚    ↓ FragmentController.mHost
β”œβ”€ androidx.fragment.app.FragmentActivity$HostCallbacks instance
β”‚    Leaking: NO (NavHostFragment↓ is not leaking)
β”‚    ↓ FragmentActivity$HostCallbacks.mFragmentManager
β”œβ”€ androidx.fragment.app.FragmentManagerImpl instance
β”‚    Leaking: NO (NavHostFragment↓ is not leaking)
β”‚    ↓ FragmentManagerImpl.mPrimaryNav
β”œβ”€ androidx.navigation.fragment.NavHostFragment instance
β”‚    Leaking: NO (LocationFragment↓ is not leaking and Fragment#mFragmentManager is not null)
β”‚    ↓ NavHostFragment.mChildFragmentManager
β”œβ”€ androidx.fragment.app.FragmentManagerImpl instance
β”‚    Leaking: NO (LocationFragment↓ is not leaking)
β”‚    ↓ FragmentManagerImpl.mFragmentStore
β”œβ”€ androidx.fragment.app.FragmentStore instance
β”‚    Leaking: NO (LocationFragment↓ is not leaking)
β”‚    ↓ FragmentStore.mActive
β”œβ”€ java.util.HashMap instance
β”‚    Leaking: NO (LocationFragment↓ is not leaking)
β”‚    ↓ HashMap.table
β”œβ”€ java.util.HashMap$Node[] array
β”‚    Leaking: NO (LocationFragment↓ is not leaking)
β”‚    ↓ HashMap$Node[].[1]
β”œβ”€ java.util.HashMap$Node instance
β”‚    Leaking: NO (LocationFragment↓ is not leaking)
β”‚    ↓ HashMap$Node.value
β”œβ”€ androidx.fragment.app.FragmentStateManager instance
β”‚    Leaking: NO (LocationFragment↓ is not leaking)
β”‚    ↓ FragmentStateManager.mFragment
β”œβ”€ com.blacklivesmatter.policebrutality.ui.incidentlocations.LocationFragment instance
β”‚    Leaking: NO (Fragment#mFragmentManager is not null)
β”‚    ↓ LocationFragment.viewDataBinding
β”‚                       ~~~~~~~~~~~~~~~
β”œβ”€ com.blacklivesmatter.policebrutality.databinding.FragmentIncidentLocationsBindingImpl instance
β”‚    Leaking: UNKNOWN
β”‚    ↓ FragmentIncidentLocationsBindingImpl.coordinator
β”‚                                           ~~~~~~~~~~~
β•°β†’ androidx.coordinatorlayout.widget.CoordinatorLayout instance
​     Leaking: YES (ObjectWatcher was watching this because com.blacklivesmatter.policebrutality.ui.incidentlocations.LocationFragment received Fragment#onDestroyView() callback (references to its views should be cleared to prevent leaks))
​     key = 720c615a-e2ef-4aa6-9ea7-38f2589310be
​     watchDurationMillis = 16342
​     retainedDurationMillis = 11340
​     mContext instance of dagger.hilt.android.internal.managers.ViewComponentManager$FragmentContextWrapper, wrapping activity com.blacklivesmatter.policebrutality.MainActivity with mDestroyed = false
​     View#mParent is null
​     View#mAttachInfo is null (view detached)
​     View.mID = R.id.coordinator
​     View.mWindowAttachCount = 1

METADATA

Build.VERSION.SDK_INT: 30
Build.MANUFACTURER: Google
LeakCanary version: 2.4
App process name: com.blacklivesmatter.policebrutality
Analysis duration: 9078 ms

ClassLoader referenced unknown path: FileNotFoundException: /jacoco.exec: open failed: EROFS

Started showing up after adding jacoco task in #177

com.blacklivesmatter.policebrutality W/System: ClassLoader referenced unknown path: /data/app/com.blacklivesmatter.policebrutality-2/lib/arm
com.blacklivesmatter.policebrutality W/System.err: java.io.FileNotFoundException: /jacoco.exec: open failed: EROFS (Read-only file system)
com.blacklivesmatter.policebrutality W/System.err:     at libcore.io.IoBridge.open(IoBridge.java:452)
com.blacklivesmatter.policebrutality W/System.err:     at java.io.FileOutputStream.<init>(FileOutputStream.java:87)
com.blacklivesmatter.policebrutality W/System.err:     at org.jacoco.agent.rt.internal_8ff85ea.output.FileOutput.openFile(FileOutput.java:67)
com.blacklivesmatter.policebrutality W/System.err:     at org.jacoco.agent.rt.internal_8ff85ea.output.FileOutput.startup(FileOutput.java:49)
com.blacklivesmatter.policebrutality W/System.err:     at org.jacoco.agent.rt.internal_8ff85ea.Agent.startup(Agent.java:122)
com.blacklivesmatter.policebrutality W/System.err:     at org.jacoco.agent.rt.internal_8ff85ea.Agent.getInstance(Agent.java:50)
com.blacklivesmatter.policebrutality W/System.err:     at org.jacoco.agent.rt.internal_8ff85ea.Offline.<clinit>(Offline.java:31)
com.blacklivesmatter.policebrutality W/System.err:     at com.blacklivesmatter.policebrutality.BrutalityIncidentApplication.$jacocoInit(BrutalityIncidentApplication.kt)
com.blacklivesmatter.policebrutality W/System.err:     at com.blacklivesmatter.policebrutality.BrutalityIncidentApplication.<init>(BrutalityIncidentApplication.kt)
com.blacklivesmatter.policebrutality W/System.err:     at java.lang.Class.newInstance(Native Method)
com.blacklivesmatter.policebrutality W/System.err:     at android.app.Instrumentation.newApplication(Instrumentation.java:996)
com.blacklivesmatter.policebrutality W/System.err:     at android.app.Instrumentation.newApplication(Instrumentation.java:981)
com.blacklivesmatter.policebrutality W/System.err:     at android.app.LoadedApk.makeApplication(LoadedApk.java:573)
com.blacklivesmatter.policebrutality W/System.err:     at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4680)
com.blacklivesmatter.policebrutality W/System.err:     at android.app.ActivityThread.-wrap1(ActivityThread.java)
com.blacklivesmatter.policebrutality W/System.err:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1405)
com.blacklivesmatter.policebrutality W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:102)
com.blacklivesmatter.policebrutality W/System.err:     at android.os.Looper.loop(Looper.java:148)
com.blacklivesmatter.policebrutality W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:5417)
com.blacklivesmatter.policebrutality W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
com.blacklivesmatter.policebrutality W/System.err:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
com.blacklivesmatter.policebrutality W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
com.blacklivesmatter.policebrutality W/System.err: Caused by: android.system.ErrnoException: open failed: EROFS (Read-only file system)
com.blacklivesmatter.policebrutality W/System.err:     at libcore.io.Posix.open(Native Method)
com.blacklivesmatter.policebrutality W/System.err:     at libcore.io.BlockGuardOs.open(BlockGuardOs.java:186)
com.blacklivesmatter.policebrutality W/System.err:     at libcore.io.IoBridge.open(IoBridge.java:438)
com.blacklivesmatter.policebrutality W/System.err: 	... 21 more

Apply the fix mentioned in jacoco/jacoco#968

Merged Manifest for 2.0

A preview of merged AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:versionCode="7"
    android:versionName="2.0"
    android:compileSdkVersion="29"
    android:compileSdkVersionCodename="10"
    package="com.blacklivesmatter.policebrutality"
    platformBuildVersionCode="29"
    platformBuildVersionName="10">

    <uses-sdk
        android:minSdkVersion="23"
        android:targetSdkVersion="29" />

    <uses-permission
        android:name="android.permission.INTERNET" />

    <uses-permission
        android:name="android.permission.WAKE_LOCK" />

    <uses-permission
        android:name="android.permission.ACCESS_NETWORK_STATE" />

    <uses-permission
        android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

    <uses-permission
        android:name="android.permission.FOREGROUND_SERVICE" />

    <uses-permission
        android:name="com.google.android.c2dm.permission.RECEIVE" />

    <uses-permission
        android:name="com.google.android.finsky.permission.BIND_GET_INSTALL_REFERRER_SERVICE" />

    <uses-permission
        android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    <uses-permission
        android:name="android.permission.READ_PHONE_STATE" />

    <uses-permission
        android:name="android.permission.READ_EXTERNAL_STORAGE" />

    <application
        android:theme="@ref/0x7f1301eb"
        android:label="@ref/0x7f12001b"
        android:icon="@ref/0x7f0f0000"
        android:name="com.blacklivesmatter.policebrutality.BrutalityIncidentApplication"
        android:allowBackup="false"
        android:supportsRtl="true"
        android:extractNativeLibs="false"
        android:roundIcon="@ref/0x7f0f0002"
        android:appComponentFactory="androidx.core.app.CoreComponentFactory">

        <activity
            android:theme="@ref/0x7f1301ec"
            android:name="com.blacklivesmatter.policebrutality.ui.launcher.LauncherActivity"
            android:launchMode="1"
            android:screenOrientation="1"
            android:windowSoftInputMode="0x10">

            <intent-filter>

                <action
                    android:name="android.intent.action.MAIN" />

                <category
                    android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <activity
            android:label="@ref/0x7f12001b"
            android:name="com.blacklivesmatter.policebrutality.MainActivity" />

        <meta-data
            android:name="preloaded_fonts"
            android:resource="@ref/0x7f030003" />

        <service
            android:name="com.google.firebase.components.ComponentDiscoveryService"
            android:exported="false"
            android:directBootAware="true">

            <meta-data
                android:name="com.google.firebase.components:com.google.firebase.crashlytics.CrashlyticsRegistrar"
                android:value="com.google.firebase.components.ComponentRegistrar" />

            <meta-data
                android:name="com.google.firebase.components:com.google.firebase.analytics.ktx.FirebaseAnalyticsKtxRegistrar"
                android:value="com.google.firebase.components.ComponentRegistrar" />

            <meta-data
                android:name="com.google.firebase.components:com.google.firebase.ktx.FirebaseCommonKtxRegistrar"
                android:value="com.google.firebase.components.ComponentRegistrar" />

            <meta-data
                android:name="com.google.firebase.components:com.google.firebase.analytics.connector.internal.AnalyticsConnectorRegistrar"
                android:value="com.google.firebase.components.ComponentRegistrar" />

            <meta-data
                android:name="com.google.firebase.components:com.google.firebase.iid.Registrar"
                android:value="com.google.firebase.components.ComponentRegistrar" />

            <meta-data
                android:name="com.google.firebase.components:com.google.firebase.installations.FirebaseInstallationsRegistrar"
                android:value="com.google.firebase.components.ComponentRegistrar" />
        </service>

        <service
            android:name="androidx.work.impl.background.systemalarm.SystemAlarmService"
            android:enabled="@ref/0x7f050004"
            android:exported="false"
            android:directBootAware="false" />

        <service
            android:name="androidx.work.impl.background.systemjob.SystemJobService"
            android:permission="android.permission.BIND_JOB_SERVICE"
            android:enabled="@ref/0x7f050006"
            android:exported="true"
            android:directBootAware="false" />

        <service
            android:name="androidx.work.impl.foreground.SystemForegroundService"
            android:enabled="@ref/0x7f050005"
            android:exported="false"
            android:directBootAware="false" />

        <receiver
            android:name="androidx.work.impl.utils.ForceStopRunnable$BroadcastReceiver"
            android:enabled="true"
            android:exported="false"
            android:directBootAware="false" />

        <receiver
            android:name="androidx.work.impl.background.systemalarm.ConstraintProxy$BatteryChargingProxy"
            android:enabled="false"
            android:exported="false"
            android:directBootAware="false">

            <intent-filter>

                <action
                    android:name="android.intent.action.ACTION_POWER_CONNECTED" />

                <action
                    android:name="android.intent.action.ACTION_POWER_DISCONNECTED" />
            </intent-filter>
        </receiver>

        <receiver
            android:name="androidx.work.impl.background.systemalarm.ConstraintProxy$BatteryNotLowProxy"
            android:enabled="false"
            android:exported="false"
            android:directBootAware="false">

            <intent-filter>

                <action
                    android:name="android.intent.action.BATTERY_OKAY" />

                <action
                    android:name="android.intent.action.BATTERY_LOW" />
            </intent-filter>
        </receiver>

        <receiver
            android:name="androidx.work.impl.background.systemalarm.ConstraintProxy$StorageNotLowProxy"
            android:enabled="false"
            android:exported="false"
            android:directBootAware="false">

            <intent-filter>

                <action
                    android:name="android.intent.action.DEVICE_STORAGE_LOW" />

                <action
                    android:name="android.intent.action.DEVICE_STORAGE_OK" />
            </intent-filter>
        </receiver>

        <receiver
            android:name="androidx.work.impl.background.systemalarm.ConstraintProxy$NetworkStateProxy"
            android:enabled="false"
            android:exported="false"
            android:directBootAware="false">

            <intent-filter>

                <action
                    android:name="android.net.conn.CONNECTIVITY_CHANGE" />
            </intent-filter>
        </receiver>

        <receiver
            android:name="androidx.work.impl.background.systemalarm.RescheduleReceiver"
            android:enabled="false"
            android:exported="false"
            android:directBootAware="false">

            <intent-filter>

                <action
                    android:name="android.intent.action.BOOT_COMPLETED" />

                <action
                    android:name="android.intent.action.TIME_SET" />

                <action
                    android:name="android.intent.action.TIMEZONE_CHANGED" />
            </intent-filter>
        </receiver>

        <receiver
            android:name="androidx.work.impl.background.systemalarm.ConstraintProxyUpdateReceiver"
            android:enabled="@ref/0x7f050004"
            android:exported="false"
            android:directBootAware="false">

            <intent-filter>

                <action
                    android:name="androidx.work.impl.background.systemalarm.UpdateProxies" />
            </intent-filter>
        </receiver>

        <service
            android:name="androidx.room.MultiInstanceInvalidationService"
            android:exported="false"
            android:directBootAware="true" />

        <receiver
            android:name="com.google.firebase.iid.FirebaseInstanceIdReceiver"
            android:permission="com.google.android.c2dm.permission.SEND"
            android:exported="true">

            <intent-filter>

                <action
                    android:name="com.google.android.c2dm.intent.RECEIVE" />
            </intent-filter>
        </receiver>

        <provider
            android:name="com.google.firebase.provider.FirebaseInitProvider"
            android:exported="false"
            android:authorities="com.blacklivesmatter.policebrutality.firebaseinitprovider"
            android:initOrder="100" />

        <activity
            android:theme="@ref/0x01030010"
            android:name="com.google.android.gms.common.api.GoogleApiActivity"
            android:exported="false" />

        <receiver
            android:name="com.google.android.gms.measurement.AppMeasurementReceiver"
            android:enabled="true"
            android:exported="false" />

        <service
            android:name="com.google.android.gms.measurement.AppMeasurementService"
            android:enabled="true"
            android:exported="false" />

        <service
            android:name="com.google.android.gms.measurement.AppMeasurementJobService"
            android:permission="android.permission.BIND_JOB_SERVICE"
            android:enabled="true"
            android:exported="false" />

        <meta-data
            android:name="com.google.android.gms.version"
            android:value="@ref/0x7f0b0009" />

        <service
            android:name="com.google.android.datatransport.runtime.backends.TransportBackendDiscovery"
            android:exported="false">

            <meta-data
                android:name="backend:com.google.android.datatransport.cct.CctBackendFactory"
                android:value="cct" />
        </service>

        <service
            android:name="com.google.android.datatransport.runtime.scheduling.jobscheduling.JobInfoSchedulerService"
            android:permission="android.permission.BIND_JOB_SERVICE"
            android:exported="false" />

        <receiver
            android:name="com.google.android.datatransport.runtime.scheduling.jobscheduling.AlarmManagerSchedulerBroadcastReceiver"
            android:exported="false" />
    </application>
</manifest>

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.