1717import org .rootio .handset .BuildConfig ;
1818import org .rootio .handset .R ;
1919import org .rootio .tools .cloud .Cloud ;
20+ import org .rootio .tools .persistence .DBAgent ;
2021import org .rootio .tools .utils .Utils ;
2122
23+ import java .io .IOException ;
24+ import java .sql .SQLException ;
25+ import java .util .ArrayList ;
26+ import java .util .Collections ;
27+ import java .util .List ;
28+ import java .util .logging .Level ;
29+ import java .util .logging .Logger ;
30+
2231/**
2332 * @author Jude Mukundane, M-ITI/IST-UL
2433 */
@@ -27,7 +36,7 @@ public class MusicListHandler implements SynchronizationHandler {
2736 private Context parent ;
2837 private Cloud cloud ;
2938 private int offset , limit = 100 ;
30- private long maxDateadded ;
39+ private String maxDateadded ;
3140
3241 MusicListHandler (Context parent , Cloud cloud ) {
3342 this .parent = parent ;
@@ -45,9 +54,8 @@ public JSONObject getSynchronizationData() {
4554 public void processJSONResponse (JSONObject synchronizationResponse ) {
4655 // do nothing with the response
4756 try {
48- if (synchronizationResponse .getBoolean ("status" ))
49- {
50- this .logMaxDateAdded (this .maxDateadded );
57+ if (synchronizationResponse .getBoolean ("status" )) {
58+ this .logMaxDateAdded (synchronizationResponse .getString ("date" ));
5159 }
5260 } catch (JSONException e ) {
5361 e .printStackTrace ();
@@ -56,32 +64,84 @@ public void processJSONResponse(JSONObject synchronizationResponse) {
5664
5765 @ Override
5866 public String getSynchronizationURL () {
59- return String .format ("%s://%s:%s/%s/%s/music?api_key=%s&version=%s_%s" , this .cloud .getServerScheme (), this .cloud .getServerAddress (), this .cloud .getHTTPPort (), "api/station" , this .cloud .getStationId (), this .cloud .getServerKey (), BuildConfig .VERSION_NAME , BuildConfig .VERSION_CODE );
60- }
67+ try {
68+ if (isSyncDue ()) {
69+ return String .format ("%s://%s:%s/%s/%s/music?api_key=%s&version=%s_%s" , this .cloud .getServerScheme (), this .cloud .getServerAddress (), this .cloud .getHTTPPort (), "api/station" , this .cloud .getStationId (), this .cloud .getServerKey (), BuildConfig .VERSION_NAME , BuildConfig .VERSION_CODE );
70+ } else {
71+ return null ;
72+ }
73+ } catch (JSONException e ) {
74+ e .printStackTrace ();
75+ return null ;
76+ }
77+ }
78+
79+ private boolean isSyncDue () throws JSONException {
80+ List <Integer > result = getMediaStatus ();
81+ if (result == null ) {
82+ return false ; //something wrong, needs looking into
83+ }
84+ String response = Utils .doPostHTTP (getPreSynchronizationURL (), "" );
85+ JSONObject status = new JSONObject (response );
86+
87+ //if the number of songs, albums or artists is different from what is on the server
88+ //and the sync date is different from what is on the server, a sync is in order
89+ boolean syncDue = !(status .getJSONObject ("songs" ).getLong ("count" ) == (long ) result .get (0 ) && status .getJSONObject ("songs" ).getString ("max_date" ).equals (getMaxDateAdded ())
90+ && status .getJSONObject ("albums" ).getLong ("count" ) == (long ) result .get (1 ) && status .getJSONObject ("albums" ).getString ("max_date" ).equals (getMaxDateAdded ())
91+ && status .getJSONObject ("artists" ).getLong ("count" ) == (long ) result .get (2 ) && status .getJSONObject ("artists" ).getString ("max_date" ).equals (getMaxDateAdded ()));
92+ Logger .getLogger ("RootIO" ).log (Level .INFO , "Media Sync Due: " + syncDue + " ( " + status + " ) and " + result .get (0 ) + ", " + getMaxDateAdded ());
93+ return syncDue ;
94+ }
95+
96+ private String getPreSynchronizationURL () {
97+ return String .format ("%s://%s:%s/%s/%s/music_status?api_key=%s&version=%s_%s" , this .cloud .getServerScheme (), this .cloud .getServerAddress (), this .cloud .getHTTPPort (), "api/station" , this .cloud .getStationId (), this .cloud .getServerKey (), BuildConfig .VERSION_NAME , BuildConfig .VERSION_CODE );
98+ }
6199
62- private long getMaxDateAdded ()
63- {
64- return ( long ) Utils . getPreference ( "media_max_date_added" , long . class , this . parent ) ;
100+ private String getMaxDateAdded () {
101+ String maxDate = ( String ) Utils . getPreference ( "media_max_date_added" , String . class , this . parent );
102+ return maxDate != null && maxDate . contains ( "." ) ? maxDate . substring ( 0 , maxDate . indexOf ( "." )) : maxDate ;
65103 }
66104
67- private void logMaxDateAdded (long maxDate ) {
105+ private void logMaxDateAdded (String maxDate ) {
68106 ContentValues values = new ContentValues ();
69107 values .put ("media_max_date_added" , maxDate );
70108 Utils .savePreferences (values , this .parent );
71109 }
72110
111+ private List <Integer > getMediaStatus () {
112+ List <Integer > result = new ArrayList <>();
113+ Cursor cur ;
114+ try {
115+ ContentResolver cr = this .parent .getContentResolver ();
116+ Uri uri = MediaStore .Audio .Media .EXTERNAL_CONTENT_URI ;
117+ String [] selection = new String []{"count (distinct " + MediaStore .Audio .Media .TITLE + ")" , "count (distinct " + MediaStore .Audio .Media .ALBUM + ")" , "count (distinct " + MediaStore .Audio .Media .ARTIST + ")" };
118+ //uncomment last bit to turn on paging in case of very many records, but in this case sort by date_added asc
119+ String sortOrder = MediaStore .Audio .Media .TITLE + " ASC" ; // limit " + String.valueOf(limit) + " offset "+String.valueOf(offset);
120+ cur = cr .query (uri , selection , null , new String []{}, sortOrder );
121+ cur .moveToFirst ();
122+ result .add (cur .getInt (0 ));
123+ result .add (cur .getInt (1 ));
124+ result .add (cur .getInt (2 ));
125+ return result ;
126+ }
127+ catch (Exception ex )
128+ {
129+ return null ;
130+ }
131+
132+ }
133+
73134 private JSONObject getSongList () {
74135 JSONObject music = new JSONObject ();
75136 String artist , album ;
76137 Cursor cur = null ;
77138 try {
78- this .maxDateadded = this .getMaxDateAdded ();
79139 ContentResolver cr = this .parent .getContentResolver ();
80140 Uri uri = MediaStore .Audio .Media .EXTERNAL_CONTENT_URI ;
81- String selection = MediaStore .Audio .Media .IS_MUSIC + "!= 0 and date_added > ? " ;
141+ String selection = MediaStore .Audio .Media .IS_MUSIC + "!= 0 and date_added " ;
82142 //uncomment last bit to turn on paging in case of very many records, but in this case sort by date_added asc
83143 String sortOrder = MediaStore .Audio .Media .TITLE + " ASC" ; // limit " + String.valueOf(limit) + " offset "+String.valueOf(offset);
84- cur = cr .query (uri , null , selection , new String []{String . valueOf ( this . maxDateadded ) }, sortOrder );
144+ cur = cr .query (uri , null , selection , new String []{}, sortOrder );
85145 offset += limit ;
86146 int count ;
87147
@@ -91,7 +151,7 @@ private JSONObject getSongList() {
91151
92152
93153 if (count > 0 ) {
94- if (count < limit ) // we have reached the end of all records!
154+ if (count < limit ) // we have reached the end of all records!
95155 {
96156 offset = 0 ;
97157 }
@@ -104,10 +164,7 @@ private JSONObject getSongList() {
104164 long dateAdded = cur .getLong (cur .getColumnIndex (MediaStore .Audio .Media .DATE_ADDED ));
105165 song .put ("date_added" , dateAdded );
106166 song .put ("date_modified" , cur .getString (cur .getColumnIndex (MediaStore .Audio .Media .DATE_MODIFIED )));
107- if (dateAdded > maxDateadded )
108- {
109- maxDateadded = dateAdded ;
110- }
167+
111168
112169 artist = cur .getString (cur .getColumnIndex (MediaStore .Audio .Media .ARTIST )) == null ? "unknown" : cur .getString (cur .getColumnIndex (MediaStore .Audio .Media .ARTIST ));
113170 artist = artist .replace ("\u2019 " , "'" ).replace ("\u2018 " , "'" );
0 commit comments