4
\$\begingroup\$

I'm happy to present my first Android project, which collects market index data (three Asian indices) and fires a notificaiton every Wednesday, Thursday and Friday at 7:30 AM displaying the data.

I've applied to Computer Science in Lund, Sweden. I am looking to improve my Java through Android development (which I've found particularly interesting).

Please consider giving some feedback. I'll be happy with anything!

MainActivity:

public class MainActivity extends AppCompatActivity {
    public static final String CHANNEL_ID = "com.example.morgonnotification.channel";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        createNotificationChannel();
        ReminderReceiver.setNextNotification(this);
    }

    private void createNotificationChannel() {
        NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "Index Channel", NotificationManager.IMPORTANCE_HIGH);
        NotificationManagerCompat.from(this).createNotificationChannel(channel);
    }

}

ReminderReceiver (BroadcastReceiver):

public class ReminderReceiver extends BroadcastReceiver {

    public static void setNextNotification(Context context) {
        AlarmManager alarmManager = (AlarmManager) context.getSystemService(ALARM_SERVICE);
        Intent intent = new Intent(context, ReminderReceiver.class);
        PendingIntent alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);

        ZonedDateTime fireTime = ZonedDateTime.now(ZoneId.of("Europe/Stockholm")).withHour(7).withMinute(30).withSecond(0);
        long nowEpochSecond = ZonedDateTime.now(ZoneId.of("Europe/Stockholm")).toEpochSecond();
        long fireTimeEpochSecond = fireTime.toEpochSecond();
        DayOfWeek day = fireTime.getDayOfWeek();

        switch (day.name()) {
            case "WEDNESDAY":
                //before 7:30 on a wednesday? Set alarm to this Wednesday morning
                fireTime = (nowEpochSecond < fireTimeEpochSecond) ? fireTime :
                        fireTime.with(TemporalAdjusters.next(DayOfWeek.THURSDAY));
                break;
            case "THURSDAY":
                //before 7:30 on a Thursday? Set alarm to this Thursday morning
                fireTime = (nowEpochSecond < fireTimeEpochSecond) ? fireTime :
                        fireTime.with(TemporalAdjusters.next(DayOfWeek.FRIDAY));

                break;
            case "FRIDAY":
                //before 7:30 on a Friday? Set alarm to this Friday morning
                fireTime = (nowEpochSecond < fireTimeEpochSecond) ? fireTime :
                        fireTime.with(TemporalAdjusters.next(DayOfWeek.WEDNESDAY));
                break;
            default:
                fireTime = fireTime.with(TemporalAdjusters.next(DayOfWeek.WEDNESDAY));
                break;
        }

        if (alarmManager != null)
            alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,
                    fireTime.toInstant().toEpochMilli(), alarmIntent);
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction()) ||
                "android.intent.action.QUICKBOOT_POWERON".equals(intent.getAction()) ||
                intent.getAction() == null) {
            setNextNotification(context);
        }

        StringBuilder indicesBuilder = new StringBuilder();
        Thread thread = new Thread(() -> {
            try {
                Document doc = Jsoup.connect("https://money.cnn.com/data/world_markets/asia//").get();

                Elements nikkei = doc.select("#wsod_indexDataTableGrid > tbody > tr:nth-child(6) > td:nth-child(5) > span > span");
                indicesBuilder.append("N: ").append(nikkei.text()).append(", ");

                Elements shanghaiComposite = doc.select("#wsod_indexDataTableGrid > tbody > tr:nth-child(3) > td:nth-child(5) > span > span");
                indicesBuilder.append(" S: ").append(shanghaiComposite.text()).append(", ");

                Elements hangSeng = doc.select("#wsod_indexDataTableGrid > tbody > tr:nth-child(4) > td:nth-child(5) > span > span");
                indicesBuilder.append(" H: ").append(hangSeng.text());

            } catch (Exception e) {
                indicesBuilder.append("Something went terribly wrong");
                e.printStackTrace();

            } finally {
                Notification notification = new NotificationCompat.Builder(context, MainActivity.CHANNEL_ID)
                        .setSmallIcon(R.drawable.ic_index)
                        .setContentTitle("Morning indices")
                        .setPriority(NotificationCompat.PRIORITY_HIGH)
                        .setStyle(new NotificationCompat.BigTextStyle().bigText(indicessBuilder)).build();

                NotificationManagerCompat manager = NotificationManagerCompat.from(context);
                manager.notify(1, notification);
                indicesBuilder.setLength(0);

            }
        });
        thread.start();

    }
}

XML File:

<?xml version="1.0" encoding="utf-8"?>

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

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <receiver
        android:name=".ReminderReceiver"
        android:enabled="true"
        android:exported="true">
        <intent-filter >
            <action android:name="android.intent.action.BOOT_COMPLETED" />
            <action android:name="android.intent.action.QUICKBOOT_POWERON" />
        </intent-filter>
    </receiver>

    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

Welcome to Code Review. Your code seems me well structured, I have two suggestions for you:

switch (day.name()) {
    case "WEDNESDAY":
         //before 7:30 on a wednesday? Set alarm to this Wednesday morning
         fireTime = (nowEpochSecond < fireTimeEpochSecond) ? fireTime :
                 fireTime.with(TemporalAdjusters.next(DayOfWeek.THURSDAY));
                 break;
    case "THURSDAY":
         //before 7:30 on a Thursday? Set alarm to this Thursday morning
         fireTime = (nowEpochSecond < fireTimeEpochSecond) ? fireTime :
                 fireTime.with(TemporalAdjusters.next(DayOfWeek.FRIDAY));
                 break;
    case "FRIDAY":
         //before 7:30 on a Friday? Set alarm to this Friday morning
         fireTime = (nowEpochSecond < fireTimeEpochSecond) ? fireTime :
                 fireTime.with(TemporalAdjusters.next(DayOfWeek.WEDNESDAY));
                 break;
    default:
         fireTime = fireTime.with(TemporalAdjusters.next(DayOfWeek.WEDNESDAY));
                 break;
}

There is code repetition and you have a binary association between one day and another one, so you could create a Map to reduce your code lines like below:

//creation of one map for the days
Map<String, String> map = new HashMap<String, String>();
map.put("WEDNESDAY", "THURSDAY");
map.put("THURSDAY" , "FRIDAY");
map.put("FRIDAY"   , "WEDNESDAY");

//here the code instead of your switch
DayOfWeek day = fireTime.getDayOfWeek();
String name = day.name();
if (map.containsKey(name)) {
    fireTime = (nowEpochSecond < fireTimeEpochSecond) ? fireTime :
               fireTime.with(TemporalAdjusters.next(DayOfWeek.valueOf(map.get(name))));
} else {
    //default value of your switch
    fireTime = fireTime.with(TemporalAdjusters.next(DayOfWeek.WEDNESDAY));
}

About the following lines in your jsoup code :

StringBuilder indicesBuilder = new StringBuilder();
indicesBuilder.append("N: ").append(nikkei.text()).append(", ");
indicesBuilder.append(" S: ").append(shanghaiComposite.text()).append(", ");
indicesBuilder.append(" H: ").append(hangSeng.text());

You can obtain the same result not going crazy about data format when you add or delete new indices using StringJoiner class:

StringJoiner sj = new StringJoiner(", ");
sj.add("N: " + nikkei.text());
sj.add("S: " + shanghaiComposite.text());
sj.add("H: " + hangSeng.text());

String bigText = sj.toString(); //<-- the string you can use later in your code.
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.