com.rp.podemu.MainActivity.java Source code

Java tutorial

Introduction

Here is the source code for com.rp.podemu.MainActivity.java

Source

/**
    
 Copyright (C) 2015, Roman P., dev.roman [at] gmail
    
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 3 of the License, or
 (at your option) any later version.
    
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
    
 You should have received a copy of the GNU General Public License
 along with this program. If not, see http://www.gnu.org/licenses/
    
 */

package com.rp.podemu;

import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.hardware.usb.UsbManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

import java.lang.ref.WeakReference;

public class MainActivity extends AppCompatActivity {

    private TextView serialStatusText = null;
    private TextView serialStatusHint = null;
    private TextView dockStatusText = null;
    private TextView ctrlAppStatusTitle = null;
    private TextView ctrlAppStatusText = null;
    private PodEmuLog podEmuLog;
    private int iPodConnected = OAPMessenger.IPOD_MODE_DISCONNECTED;

    private String ctrlAppProcessName;
    private Intent serviceIntent;
    private SerialInterfaceBuilder serialInterfaceBuilder;
    private PodEmuIntentFilter iF;
    private PodEmuService podEmuService;
    private boolean serviceBound = false;
    public PodEmuMessage currentlyPlaying = new PodEmuMessage();

    //public static LooperThread looperThread;

    public void setCtrlAppProcessName(String processName) {
        ctrlAppProcessName = processName;
    }

    public String getCtrlAppProcessName() {
        return ctrlAppProcessName;
    }

    public void action_next(View v) {
        MediaPlayback mediaPlayback = MediaPlayback.getInstance();
        mediaPlayback.action_next();
    }

    public void action_play_pause(View v) {
        MediaPlayback mediaPlayback = MediaPlayback.getInstance();
        mediaPlayback.action_play_pause();

    }

    public void action_prev(View v) {
        MediaPlayback mediaPlayback = MediaPlayback.getInstance();
        mediaPlayback.action_prev(0);
    }

    public void start_stop_service(View v) {
        if (serviceBound) {
            PodEmuLog.debug("Stop service initiated...");
            stop_service(v);
        } else {
            PodEmuLog.debug("Start service initiated...");
            start_service(v);
        }
    }

    public void start_service(View v) {

        try {
            SerialInterface serialInterface = serialInterfaceBuilder
                    .getSerialInterface((UsbManager) getSystemService(Context.USB_SERVICE));
            // reconnect usb

            updateSerialStatus();
            if (serialInterface != null) {
                startService(serviceIntent);

                if (bindService(serviceIntent, serviceConnection, BIND_IMPORTANT)) {
                    PodEmuLog.debug("Service succesfully bound");
                    serviceBound = true;
                } else {
                    PodEmuLog.debug("Service NOT bound");
                }

                updateServiceButton();
            }

        } catch (Exception e) {
            PodEmuLog.printStackTrace(e);
            throw e;
        }

    }

    public void stop_service(View v) {
        try {
            iPodConnected = OAPMessenger.IPOD_MODE_DISCONNECTED;
            unbindService(serviceConnection);
            stopService(serviceIntent);
            serviceBound = false;
            updateSerialStatus();
            updateServiceButton();
            updateIPodStatus();
        } catch (Exception e) {
            PodEmuLog.printStackTrace(e);
            throw e;
        }

    }

    private void updateServiceButton() {
        Button srvcButton = (Button) findViewById(R.id.button_start_stop_srvc);
        if (serviceBound)
            srvcButton.setText("STOP SRVC");
        else
            srvcButton.setText("START SRVC");

    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        try {
            PodEmuLog.debug("onCreate");
            setContentView(R.layout.activity_main);
            // required to create logdir
            podEmuLog = new PodEmuLog(this);
            podEmuLog.printSystemInfo();

            // Make scroll view automatically scroll to the bottom
            /*        final ScrollView sv=(ScrollView) this.findViewById(R.id.main_sv);
                    sv.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener()
                       {
                           @Override
                
                           public void onGlobalLayout()
                           {
               sv.post(new Runnable()
               {
                
                   public void run()
                   {
                       sv.fullScroll(ScrollView.FOCUS_DOWN);
                   }
               });
                           }
                       });
            */
            serialInterfaceBuilder = new SerialInterfaceBuilder();

            //        LayoutInflater lif = getLayoutInflater();
            //        ViewGroup layout = (ViewGroup)lif.inflate(R.layout.board, null);
            dockingLogoView = (DockingLogoView) findViewById(R.id.dockStationLogo);
            //        layout.addView((View)dockingLogoView);

            //        loadPreferences();

            this.ctrlAppStatusTitle = (TextView) this.findViewById(R.id.CTRL_app_status_title);
            this.ctrlAppStatusText = (TextView) this.findViewById(R.id.CTRL_app_status_text);
            this.serialStatusText = (TextView) this.findViewById(R.id.SERIAL_status_text);
            this.serialStatusHint = (TextView) this.findViewById(R.id.SERIAL_status_hint);
            this.dockStatusText = (TextView) this.findViewById(R.id.DOCK_status_text);

            //AudioManager manager = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
            //if (!manager.isMusicActive())
            //{
            //    this.mainText.setText("Not playing...");
            //}

            // Start background service
            serviceIntent = new Intent(this, PodEmuService.class);

            updateSerialStatus();
            updateIPodStatus();
        } catch (Exception e) {
            PodEmuLog.printStackTrace(e);
            throw e;
        }

        try {
            PackageInfo pInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
            String version = pInfo.versionName;

            setTitle(getTitle() + " " + version);
        } catch (PackageManager.NameNotFoundException e) {
            // do nothing
        }
    }

    private BroadcastReceiver mReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {
            try {
                PodEmuMessage podEmuMessage = PodEmuIntentFilter.processBroadcast(context, intent);

                // if null is received then broadcast could be not from "our" app
                if (podEmuMessage != null) {
                    currentlyPlaying.bulk_update(podEmuMessage);
                    if (podEmuMessage.getAction() != PodEmuMessage.ACTION_QUEUE_CHANGED) {
                        updateCurrentlyPlayingDisplay();
                    }
                }
            } catch (Exception e) {
                PodEmuLog.printStackTrace(e);
                throw e;
            }

        }
    };

    private void loadPreferences() {
        try {
            ImageView appLogo = (ImageView) findViewById(R.id.CTRL_app_icon);
            SharedPreferences sharedPref = this.getSharedPreferences("PODEMU_PREFS", Context.MODE_PRIVATE);
            ctrlAppProcessName = sharedPref.getString("ControlledAppProcessName", "unknown app");
            String enableDebug = sharedPref.getString("enableDebug", "false");
            Boolean ctrlAppUpdated = sharedPref.getBoolean("ControlledAppUpdated", false);

            if (PodEmuMediaStore.getInstance() == null) {
                PodEmuMediaStore.initialize(this);
            }

            // update ctrlApp only if it was changed or MediaPlayback engine is not yet initialized
            if (ctrlAppUpdated || MediaPlayback.getInstance() == null) {
                PodEmuMediaStore.getInstance().setCtrlAppProcessName(ctrlAppProcessName);
            }

            if (enableDebug.equals("true"))
                PodEmuLog.DEBUG_LEVEL = 2;
            else
                PodEmuLog.DEBUG_LEVEL = 0;

            if (podEmuService != null) {
                podEmuService.reloadBaudRate();
            }

            if (MediaPlayback.getInstance() != null) {
                currentlyPlaying.bulk_update(
                        MediaPlayback.getInstance().getCurrentPlaylist().getCurrentTrack().toPodEmuMessage());
                updateCurrentlyPlayingDisplay();
            }

            PackageManager pm = getPackageManager();
            ApplicationInfo appInfo;

            try {
                appInfo = pm.getApplicationInfo(ctrlAppProcessName, PackageManager.GET_META_DATA);

                ctrlAppStatusTitle.setText("Controlled app: " + appInfo.loadLabel(pm));
                ctrlAppStatusTitle.setTextColor(Color.rgb(0xff, 0xff, 0xff));

                if (ctrlAppUpdated && currentlyPlaying.isPlaying()) {
                    // invoke play_pause button to switch the app
                    MediaPlayback mediaPlayback = MediaPlayback.getInstance();
                    mediaPlayback.action_play_pause();
                }
                SharedPreferences.Editor editor = sharedPref.edit();
                editor.putBoolean("ControlledAppUpdated", false);
                editor.apply();

                appLogo.setImageDrawable(appInfo.loadIcon(pm));
            } catch (PackageManager.NameNotFoundException e) {
                ctrlAppStatusTitle.setText("Please go to the settings and setup controlled music application");
                ctrlAppStatusTitle.setTextColor(Color.rgb(0xff, 0x00, 0x00));

                appLogo.setImageDrawable(ContextCompat.getDrawable(this, (R.drawable.questionmark)));
            }
        } catch (Exception e) {
            PodEmuLog.printStackTrace(e);
            throw e;
        }

    }

    @Override
    protected void onPause() {
        super.onPause();

        try {
            unregisterReceiver(mReceiver);

            PodEmuLog.debug("onPause done");
        } catch (Exception e) {
            PodEmuLog.printStackTrace(e);
            throw e;
        }

    }

    @Override
    public void onResume() {
        super.onResume();

        try {
            loadPreferences();
            start_service(null);

            iF = new PodEmuIntentFilter();
            iF.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
            iF.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
            //            iF.addDataScheme("content");
            //            iF.addDataAuthority(ctrlAppProcessName, null);

            registerReceiver(mReceiver, iF);

            PodEmuLog.debug("onResume done");
        } catch (Exception e) {
            PodEmuLog.printStackTrace(e);
            throw e;
        }

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

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

        try {
            PodEmuLog.debug("onDestroy");
            //unregisterReceiver(mReceiver);
            //stopService(serviceIntent);

            if (serviceBound) {
                unbindService(serviceConnection);
                serviceBound = false;
            }

            // this is main thread looper, so no need to quit()
            //mHandler.getLooper().quit();
        } catch (Exception e) {
            PodEmuLog.printStackTrace(e);
            throw e;
        }

    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_menu_settings) {

            Intent intent = new Intent(this, SettingsActivity.class);
            startActivity(intent);

            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    private void updateSerialStatus() {
        SerialInterface serialInterface = serialInterfaceBuilder
                .getSerialInterface((UsbManager) getSystemService(Context.USB_SERVICE));
        if (serialInterface != null) {
            this.serialStatusText.setTextColor(Color.rgb(0x00, 0xff, 0x00));
            this.serialStatusText.setText("connected");

            this.serialStatusHint.setText(String.format("VID: 0x%04X, ", serialInterface.getVID())
                    + String.format("PID: 0x%04X\n", serialInterface.getPID()) + "Cable: "
                    + serialInterface.getName());
        } else {
            this.serialStatusText.setTextColor(Color.rgb(0xff, 0x00, 0x00));
            this.serialStatusText.setText("disconnected");

            this.serialStatusHint.setText(R.string.serial_status_hint);
        }
    }

    private void updateIPodStatus() {
        try {
            if (iPodConnected == OAPMessenger.IPOD_MODE_AIR) {
                this.dockStatusText.setTextColor(Color.rgb(0x00, 0xff, 0x00));
                this.dockStatusText.setText("AiR mode");
                if (podEmuService.isDockIconLoaded) {
                    dockingLogoView.setBitmap(podEmuService.dockIconBitmap);
                }
            } else if (iPodConnected == OAPMessenger.IPOD_MODE_SIMPLE) {
                this.dockStatusText.setTextColor(Color.rgb(0x00, 0xff, 0x00));
                this.dockStatusText.setText("simple mode");
            } else // docking station disconnected
            {
                this.dockStatusText.setTextColor(Color.rgb(0xff, 0x00, 0x00));
                this.dockStatusText.setText("disconnected");

                if (dockingLogoView != null) {
                    dockingLogoView.resetBitmap();
                    if (podEmuService != null) {
                        podEmuService.dockIconBitmap = dockingLogoView.getResizedBitmap();
                    }
                }
            }
        } catch (Exception e) {
            PodEmuLog.printStackTrace(e);
            throw e;
        }

    }

    private void updateCurrentlyPlayingDisplay() {
        ctrlAppStatusText.setText("Artist: " + currentlyPlaying.getArtist() + "\n" + " Album: "
                + currentlyPlaying.getAlbum() + "\n" + " Track: " + currentlyPlaying.getTrackName() + "\n"
                + "Length: " + currentlyPlaying.getLengthHumanReadable() + "\n");

    }

    // Defines a Handler object that's attached to the UI thread
    //Handler mHandler = new Handler(Looper.getMainLooper());
    myHandler mHandler = new myHandler(this);

    private class myHandler extends Handler {
        private final WeakReference<MainActivity> mainActivityWeakReference;

        myHandler(MainActivity context) {
            mainActivityWeakReference = new WeakReference<MainActivity>((MainActivity) context);
            //this.Handler(looper);
        }

        /*
        * handleMessage() defines the operations to perform when
        * the Handler receives a new Message to process.
        */
        @Override
        public void handleMessage(Message inputMessage) {
            super.handleMessage(inputMessage);

            try {
                MainActivity target = mainActivityWeakReference.get();
                // Gets the image task from the incoming Message object.
                //        PhotoTask photoTask = (PhotoTask) inputMessage.obj;
                //mainText.setText(mainText.getText() + "Received MSG");
                switch (inputMessage.arg1) {
                case 1: // we received a picture block
                {
                    dockingLogoView.setBitmap((Bitmap) inputMessage.obj);
                    podEmuService.dockIconBitmap = dockingLogoView.getResizedBitmap();
                    podEmuService.isDockIconLoaded = true;
                }
                    break;
                case 2: // dock station connection status changed
                {
                    iPodConnected = inputMessage.arg2;
                    updateIPodStatus();
                }
                    break;
                case 3: // serial connection status changed
                {
                    updateSerialStatus();
                }
                    break;
                }
            } catch (Exception e) {
                PodEmuLog.printStackTrace(e);
                throw e;
            }

        }
    }

    DockingLogoView dockingLogoView;

    /** Defines callbacks for service binding, passed to bindService() */
    private ServiceConnection serviceConnection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName className, IBinder service) {
            try {
                // We've bound to LocalService, cast the IBinder and get LocalService instance
                PodEmuService.LocalBinder binder = (PodEmuService.LocalBinder) service;
                podEmuService = binder.getService();
                serviceBound = true;
                podEmuService.setHandler(mHandler);
                podEmuService.setMediaEngine();

                if (currentlyPlaying.getTrackName() != null) {
                    // update service only if we have this information
                    // otherwise we can overwrite information that service already has (eg. if we are rebinding)
                    podEmuService.registerMessage(currentlyPlaying);
                } else {
                    // otherwise update currently playing
                    currentlyPlaying.bulk_update(podEmuService.getCurrentlyPlaying());
                    updateCurrentlyPlayingDisplay();
                }
                updateServiceButton();

                if (podEmuService.dockIconBitmap != null) {
                    dockingLogoView.setResizedBitmap(podEmuService.dockIconBitmap);
                }

                // once service is bound we can launch controlled app
                if (!podEmuService.isAppLaunched) {
                    launchControlledApp(null);
                    podEmuService.isAppLaunched = true;
                }
            } catch (Exception e) {
                PodEmuLog.printStackTrace(e);
                throw e;
            }

        }

        @Override
        public void onServiceDisconnected(ComponentName arg0) {
            serviceBound = false;
            updateServiceButton();
        }
    };

    public void launchControlledApp(View v) {
        try {
            Intent intent = getPackageManager().getLaunchIntentForPackage(ctrlAppProcessName);
            if (intent != null)
                startActivity(intent);
        } catch (Exception e) {
            PodEmuLog.printStackTrace(e);
            throw e;
        }

    }

}