Skip to content

Commit 7739f93

Browse files
Merge pull request #11 from D4rK7355608/codex/implement-app-rotation-for-promo-display
Add rotating promotions from remote list
2 parents 736b10d + 5187f71 commit 7739f93

File tree

4 files changed

+106
-39
lines changed

4 files changed

+106
-39
lines changed
Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
package com.d4rk.androidtutorials.java.data.model;
22

3-
import androidx.annotation.DrawableRes;
4-
import androidx.annotation.StringRes;
3+
/**
4+
* Model representing a promoted application fetched from the remote API.
5+
*/
6+
public class PromotedApp {
57

6-
public record PromotedApp(
7-
@DrawableRes int iconResId,
8-
@StringRes int nameResId,
9-
@StringRes int descriptionResId,
10-
String packageName
11-
) {}
8+
public final String name;
9+
public final String packageName;
10+
public final String iconUrl;
11+
12+
public PromotedApp(String name, String packageName, String iconUrl) {
13+
this.name = name;
14+
this.packageName = packageName;
15+
this.iconUrl = iconUrl;
16+
}
17+
}

app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/home/HomeFragment.java

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,29 @@ private void shareTip(String tip) {
6666

6767
private void setupPromotions(LayoutInflater inflater) {
6868
ViewGroup container = binding.promotedAppsContainer;
69-
for (com.d4rk.androidtutorials.java.data.model.PromotedApp app : homeViewModel.getPromotedApps()) {
70-
com.d4rk.androidtutorials.java.databinding.PromotedAppItemBinding itemBinding =
71-
com.d4rk.androidtutorials.java.databinding.PromotedAppItemBinding.inflate(inflater, container, false);
72-
itemBinding.appIcon.setImageResource(app.iconResId());
73-
itemBinding.appName.setText(app.nameResId());
74-
itemBinding.appDescription.setText(app.descriptionResId());
75-
itemBinding.appButton.setOnClickListener(v -> startActivity(homeViewModel.getPromotedAppIntent(app.packageName())));
76-
container.addView(itemBinding.getRoot());
77-
}
69+
homeViewModel.getPromotedApps().observe(getViewLifecycleOwner(), apps -> {
70+
container.removeAllViews();
71+
for (com.d4rk.androidtutorials.java.data.model.PromotedApp app : apps) {
72+
com.d4rk.androidtutorials.java.databinding.PromotedAppItemBinding itemBinding =
73+
com.d4rk.androidtutorials.java.databinding.PromotedAppItemBinding.inflate(inflater, container, false);
74+
loadImage(app.iconUrl, itemBinding.appIcon);
75+
itemBinding.appName.setText(app.name);
76+
itemBinding.appDescription.setVisibility(android.view.View.GONE);
77+
itemBinding.appButton.setOnClickListener(v -> startActivity(homeViewModel.getPromotedAppIntent(app.packageName)));
78+
container.addView(itemBinding.getRoot());
79+
}
80+
});
81+
}
82+
83+
private void loadImage(String url, android.widget.ImageView imageView) {
84+
com.android.volley.toolbox.ImageRequest request = new com.android.volley.toolbox.ImageRequest(
85+
url,
86+
imageView::setImageBitmap,
87+
0,
88+
0,
89+
android.widget.ImageView.ScaleType.CENTER_INSIDE,
90+
android.graphics.Bitmap.Config.ARGB_8888,
91+
error -> {});
92+
com.android.volley.toolbox.Volley.newRequestQueue(requireContext()).add(request);
7893
}
7994
}

app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/home/HomeViewModel.java

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public class HomeViewModel extends AndroidViewModel {
2323
private final MutableLiveData<String> announcementTitle = new MutableLiveData<>();
2424
private final MutableLiveData<String> announcementSubtitle = new MutableLiveData<>();
2525
private final MutableLiveData<String> dailyTip = new MutableLiveData<>();
26-
private final List<PromotedApp> promotedApps = new ArrayList<>();
26+
private final MutableLiveData<List<PromotedApp>> promotedApps = new MutableLiveData<>(new ArrayList<>());
2727

2828
public HomeViewModel(@NonNull Application application) {
2929
super(application);
@@ -33,26 +33,18 @@ public HomeViewModel(@NonNull Application application) {
3333
announcementSubtitle.setValue(application.getString(R.string.announcement_subtitle));
3434
dailyTip.setValue(homeRepository.getDailyTip());
3535

36-
promotedApps.add(new PromotedApp(
37-
R.drawable.ic_shop,
38-
R.string.cart_calculator_name,
39-
R.string.cart_calculator_description,
40-
application.getString(R.string.package_cart_calculator)));
41-
promotedApps.add(new PromotedApp(
42-
R.drawable.ic_safety_check_tinted,
43-
R.string.cleaner_android_name,
44-
R.string.cleaner_android_description,
45-
application.getString(R.string.package_cleaner_android)));
46-
promotedApps.add(new PromotedApp(
47-
R.drawable.ic_build_tinted,
48-
R.string.apptoolkit_android_name,
49-
R.string.apptoolkit_android_description,
50-
application.getString(R.string.package_apptoolkit_android)));
51-
promotedApps.add(new PromotedApp(
52-
R.drawable.ic_code,
53-
R.string.qr_scanner_name,
54-
R.string.qr_scanner_description,
55-
application.getString(R.string.package_qr_scanner)));
36+
homeRepository.fetchPromotedApps(apps -> {
37+
if (apps.isEmpty()) {
38+
promotedApps.postValue(apps);
39+
return;
40+
}
41+
int startIndex = (int) ((System.currentTimeMillis() / (24L * 60 * 60 * 1000)) % apps.size());
42+
List<PromotedApp> rotated = new ArrayList<>();
43+
for (int i = 0; i < Math.min(4, apps.size()); i++) {
44+
rotated.add(apps.get((startIndex + i) % apps.size()));
45+
}
46+
promotedApps.postValue(rotated);
47+
});
5648
}
5749

5850
/**
@@ -87,7 +79,7 @@ public Intent getOpenPlayStoreIntent() {
8779
/**
8880
* List of apps to promote on the Home screen.
8981
*/
90-
public List<PromotedApp> getPromotedApps() {
82+
public LiveData<List<PromotedApp>> getPromotedApps() {
9183
return promotedApps;
9284
}
9385

app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/home/repository/HomeRepository.java

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,39 @@
22

33
import android.content.Context;
44
import android.content.Intent;
5+
import android.graphics.Bitmap;
56
import android.net.Uri;
7+
8+
import com.android.volley.Request;
9+
import com.android.volley.RequestQueue;
10+
import com.android.volley.toolbox.ImageRequest;
11+
import com.android.volley.toolbox.JsonObjectRequest;
12+
import com.android.volley.toolbox.Volley;
613
import com.d4rk.androidtutorials.java.BuildConfig;
714
import com.d4rk.androidtutorials.java.R;
15+
import com.d4rk.androidtutorials.java.data.model.PromotedApp;
16+
17+
import org.json.JSONArray;
18+
import org.json.JSONException;
19+
import org.json.JSONObject;
820

21+
import java.util.ArrayList;
22+
import java.util.Collections;
23+
import java.util.List;
924
/**
1025
* Repository for Home screen data/logic.
1126
* Here you can manage fetching or storing any data needed on the HomeFragment.
1227
*/
1328
public class HomeRepository {
1429

1530
private final Context context;
31+
private final RequestQueue requestQueue;
32+
private static final String PROMOTED_APPS_URL =
33+
"https://raw.githubusercontent.com/D4rK7355608/com.d4rk.apis/refs/heads/main/App%20Toolkit/release/en/home/api_android_apps.json";
1634

1735
public HomeRepository(Context context) {
1836
this.context = context.getApplicationContext();
37+
this.requestQueue = Volley.newRequestQueue(this.context);
1938
}
2039

2140
/**
@@ -48,4 +67,39 @@ public String getDailyTip() {
4867
int index = (int) (daysSinceEpoch % tips.length);
4968
return tips[index];
5069
}
70+
71+
/** Callback used for delivering promoted apps. */
72+
public interface PromotedAppsCallback {
73+
void onResult(List<PromotedApp> apps);
74+
}
75+
76+
/**
77+
* Fetches the promoted apps list from the remote JSON API.
78+
*/
79+
public void fetchPromotedApps(PromotedAppsCallback callback) {
80+
JsonObjectRequest request = new JsonObjectRequest(
81+
Request.Method.GET,
82+
PROMOTED_APPS_URL,
83+
null,
84+
response -> {
85+
List<PromotedApp> result = new ArrayList<>();
86+
try {
87+
JSONArray apps = response.getJSONObject("data").getJSONArray("apps");
88+
for (int i = 0; i < apps.length(); i++) {
89+
JSONObject obj = apps.getJSONObject(i);
90+
result.add(new PromotedApp(
91+
obj.getString("name"),
92+
obj.getString("packageName"),
93+
obj.getString("iconLogo")
94+
));
95+
}
96+
} catch (JSONException e) {
97+
result = Collections.emptyList();
98+
}
99+
callback.onResult(result);
100+
},
101+
error -> callback.onResult(Collections.emptyList())
102+
);
103+
requestQueue.add(request);
104+
}
51105
}

0 commit comments

Comments
 (0)