Android Open Source - RadioRake Recorder Service






From Project

Back to project page RadioRake.

License

The source code is released under:

GNU General Public License

If you think the Android project RadioRake listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.asp.radiorake.recording;
/*from  w w  w. j  a v  a  2s.c  om*/
import android.app.Notification;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;

import com.commonsware.cwac.wakeful.WakefulIntentService;
import com.asp.radiorake.NotificationHelper;
import com.asp.radiorake.RadioApplication;
import com.asp.radiorake.RadioDetails;
import com.asp.radiorake.filehandling.M3uHandler;
import com.asp.radiorake.filehandling.PlsHandler;
import com.asp.radiorake.utils.StringUtils;
import com.aspillai.R;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Calendar;
import java.util.GregorianCalendar;

public class RecorderService extends WakefulIntentService {

    private static final String TAG = "com.asp.radiorake.RecorderService";

    private FileOutputStream fileOutputStream;
    private InputStream inputStream;

    private static boolean recordingState = false;
    private static boolean cancelRecordingFlag = false;

    public RecorderService() {
        super("RecorderService");
    }

    @Override
    protected void doWakefulWork(Intent intent) {

        Bundle bundle = intent.getExtras();
        RadioApplication radioApplication = (RadioApplication) getApplication();
        RadioDetails radioDetails = bundle.getParcelable(getString(R.string.radio_details_key));

        if (!android.os.Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            // Cannot write to SDCARD, so stuffed!
            String error = "Failed to record " + radioDetails.getStationName() + " cannot write to SD Card";
            Notification errorNotification = NotificationHelper.getNotification(this, NotificationHelper.NOTIFICATION_RECORDING_ID, radioDetails, error, error, Notification.FLAG_ONLY_ALERT_ONCE);
            ((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).notify(NotificationHelper.NOTIFICATION_RECORDING_ID, errorNotification);
            updateActivity(error);
            Log.e(TAG, error);
            return;
        }

        ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        if (connectivityManager.getActiveNetworkInfo() == null || !connectivityManager.getActiveNetworkInfo().isConnected()) {
            // No network connection
            String error = "Failed to record " + radioDetails.getStationName() + ", no network available";
            Notification errorNotification = NotificationHelper.getNotification(this, NotificationHelper.NOTIFICATION_RECORDING_ID, radioDetails, error, error, Notification.FLAG_ONLY_ALERT_ONCE);
            ((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).notify(NotificationHelper.NOTIFICATION_RECORDING_ID, errorNotification);
            updateActivity(error);
            Log.e(TAG, error);
            return;
        }

        // SDCARD must be writable and network available, so here we go...

        if (radioDetails.getPlaylistUrl().endsWith(".pls") || radioDetails.getPlaylistUrl().endsWith(".m3u")) {
            if (radioDetails.getPlaylistUrl().endsWith(".pls")) {
                radioDetails = PlsHandler.parse(radioDetails, getApplicationContext().getFilesDir().getPath());
            } else {
                radioDetails = M3uHandler.parse(radioDetails, this.getApplicationContext().getFilesDir().getPath());
            }
        } else {
            radioDetails.setStreamUrl(radioDetails.getPlaylistUrl());
        }

        CharSequence ticketText = new StringBuilder()
                .append(getString(R.string.recording_string))
                .append(" ")
                .append(radioDetails.getStationName())
                .toString();

        Notification notification = NotificationHelper.getNotification(this, NotificationHelper.NOTIFICATION_RECORDING_ID, radioDetails, ticketText, ticketText, Notification.FLAG_ONGOING_EVENT);
        startForeground(NotificationHelper.NOTIFICATION_RECORDING_ID, notification);
        updateActivity(ticketText.toString());

        String recFolder = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + getString(R.string.app_name);

        if (!new File(recFolder).exists()) {
            if (!(new File(recFolder).mkdir())) {
                //Failed to create dir, so have to quit
                String error = "Failed to record " + radioDetails.getStationName() + " cannot create directory to store recordings";
                Notification errorNotification = NotificationHelper.getNotification(this, NotificationHelper.NOTIFICATION_RECORDING_ID, radioDetails, error, error, Notification.FLAG_ONLY_ALERT_ONCE);
                ((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).notify(NotificationHelper.NOTIFICATION_RECORDING_ID, errorNotification);
                updateActivity(error);
                return;
            }
            Log.d(TAG, "Recordio directory was not found, so created it");
        }

        StringBuilder outputSource = new StringBuilder()
                .append(recFolder)
                .append(File.separator);

        if (!StringUtils.IsNullOrEmpty(radioDetails.getStationName())) {
            outputSource.append(radioDetails.getStationName())
                    .append("-");
        }

        outputSource.append(getTimestamp())
                .append(".mp3");

        Log.d(TAG, "Writing stream to : " + outputSource);

        WifiManager wm = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        WifiManager.WifiLock wifiLock = wm.createWifiLock(WifiManager.WIFI_MODE_FULL, "MyWifiLock");

        if (!wifiLock.isHeld()) {
            wifiLock.acquire();
        }

        radioApplication.setRecordingStation(radioDetails);

        try {


            byte[] buffer = new byte[4096];

            URLConnection url = new URL(radioDetails.getStreamUrl()).openConnection();
            inputStream = url.getInputStream();
            fileOutputStream = new FileOutputStream(outputSource.toString());
            recordingState = true;

            long endTime = radioDetails.getDuration() > 0 ? System.currentTimeMillis() + radioDetails.getDuration() : 0;

            record(radioDetails, outputSource.toString(), buffer, endTime);
            Log.d(TAG, "Finished writing stream");
            updateActivity("");

        } catch (MalformedURLException e) {
            Log.e(TAG, "Uri malformed: " + e.getMessage(), e);
        } catch (IOException e) {
            Log.e(TAG, "IOException: " + e.getMessage(), e);
            // Expected when stream closes
        } finally {

            try {
                if (inputStream != null) {
                    inputStream.close();
                    inputStream = null;
                }
                if (fileOutputStream != null) {
                    fileOutputStream.flush();
                    fileOutputStream.close();
                    fileOutputStream = null;
                }

                wifiLock.release();
                recordingState = false;
                cancelRecordingFlag = false;

            } catch (IOException e) {
                Log.e(TAG, "Error flushing and close output stream", e);
            }

        }
    }

    private void record(RadioDetails radioDetails, String outputSource, byte[] buffer, long endTime) {
        try {
            int len;
            URLConnection url = new URL(radioDetails.getStreamUrl()).openConnection();
            inputStream = url.getInputStream();
            fileOutputStream = new FileOutputStream(outputSource, true);

            if (endTime > 0) {
                Log.d(TAG, "Starting timed recording for " + radioDetails.getStreamUrl());
                while (!cancelRecordingFlag && (System.currentTimeMillis() < endTime) && (len = inputStream.read(buffer)) > 0) {
                    fileOutputStream.write(buffer, 0, len);
                }
            } else {
                Log.d(TAG, "Starting manual recording for " + radioDetails.getStreamUrl());
                while (!cancelRecordingFlag && (len = inputStream.read(buffer)) > 0) {
                    fileOutputStream.write(buffer, 0, len);
                }
            }

        } catch (IOException ignored) {
            try {
                // 1 second delay
                Thread.sleep(1000);
            } catch (InterruptedException ignored2) {
                Log.d(TAG, "Sleep interrupted");
            }
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    @Override
    public void onLowMemory() {
        super.onDestroy();
        Log.d(TAG, "onLowMemory called");
    }

    private String getTimestamp() {

        Calendar calendar = new GregorianCalendar();

        StringBuilder timestamp = new StringBuilder();
        timestamp.append(calendar.get(Calendar.YEAR));
        timestamp.append(("."));
        // As months are 0 indexed + 1
        timestamp.append(StringUtils.pad(calendar.get(Calendar.MONTH) + 1));
        timestamp.append(("."));
        timestamp.append(StringUtils.pad(calendar.get(Calendar.DAY_OF_MONTH)));
        timestamp.append(("-"));
        timestamp.append(StringUtils.pad(calendar.get(Calendar.HOUR_OF_DAY)));
        timestamp.append(("."));
        timestamp.append(StringUtils.pad(calendar.get(Calendar.MINUTE)));
        timestamp.append(("."));
        timestamp.append(StringUtils.pad(calendar.get(Calendar.SECOND)));

        return timestamp.toString();
    }

    public static boolean alreadyRecording() {
        return recordingState;
    }

    public static void cancelRecording() {
        Log.d(TAG, "Cancel recording stream");
        cancelRecordingFlag = true;
    }

    private void updateActivity(String text) {
        Intent intent = new Intent(getString(R.string.player_service_update_playing_key));
        ((RadioApplication) getApplication()).setRecordingStatus(text);
        getApplicationContext().sendBroadcast(intent);
    }
}




Java Source Code List

com.asp.radiorake.AddNewScheduledRecordingActivity.java
com.asp.radiorake.AlarmHelper.java
com.asp.radiorake.CallReceiver.java
com.asp.radiorake.ConfirmDetailsActivity.java
com.asp.radiorake.DatabaseHelper.java
com.asp.radiorake.DatePickerFragment.java
com.asp.radiorake.LastPlayedFile.java
com.asp.radiorake.ListScheduledRecordingsActivity.java
com.asp.radiorake.NotificationHelper.java
com.asp.radiorake.PlayerService.java
com.asp.radiorake.PlayingFile.java
com.asp.radiorake.RadioActivity.java
com.asp.radiorake.RadioApplication.java
com.asp.radiorake.RadioDetails.java
com.asp.radiorake.RebootBroadcastReceiver.java
com.asp.radiorake.RecordingsActivity.java
com.asp.radiorake.RecordioBaseActivity.java
com.asp.radiorake.RemoteControlReceiver.java
com.asp.radiorake.ScheduledRecordingsCursorAdaptor.java
com.asp.radiorake.TimePickerFragment.java
com.asp.radiorake.filehandling.FileHandler.java
com.asp.radiorake.filehandling.M3uHandler.java
com.asp.radiorake.filehandling.PlsHandler.java
com.asp.radiorake.recording.RecorderService.java
com.asp.radiorake.recording.RecordingBroadcastReceiver.java
com.asp.radiorake.utils.DateUtils.java
com.asp.radiorake.utils.StringUtils.java