package net.rdrei.android.scdl2.ui; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import com.google.android.gms.analytics.HitBuilders; import com.google.android.gms.analytics.Tracker; import com.google.inject.Inject; import com.google.inject.Provider; import com.squareup.picasso.Picasso; import net.rdrei.android.scdl2.ApplicationPreferences; import net.rdrei.android.scdl2.R; import net.rdrei.android.scdl2.RoboContractFragment; import net.rdrei.android.scdl2.TrackDownloader; import net.rdrei.android.scdl2.TrackDownloaderFactory; import net.rdrei.android.scdl2.api.MediaState; import net.rdrei.android.scdl2.api.ServiceManager; import net.rdrei.android.scdl2.api.entity.TrackEntity; import net.rdrei.android.scdl2.api.service.DownloadService; import de.keyboardsurfer.android.widget.crouton.Crouton; import de.keyboardsurfer.android.widget.crouton.Style; import roboguice.inject.InjectView; import roboguice.util.Ln; import roboguice.util.RoboAsyncTask; /** * Fragment for downloading a single track, used by DownloadActivity. */ public class DownloadTrackFragment extends RoboContractFragment<DownloadMediaContract> { @InjectView(R.id.track_title) private TextView mTitleView; @InjectView(R.id.track_description) private TextView mDescriptionView; @InjectView(R.id.detail_container) private View mDetailContainerView; @InjectView(R.id.track_unavailable) private TextView mTrackUnavailableView; @InjectView(R.id.progress_bar) private View mProgressBarView; @InjectView(R.id.btn_download) private Button mDownloadButton; @InjectView(R.id.btn_remove_ads) private Button mRemoveAdsButton; @InjectView(R.id.img_artwork) private ImageView mArtworkImageView; @InjectView(R.id.track_length) private TextView mLengthView; @InjectView(R.id.track_artist) private TextView mArtistView; @InjectView(R.id.track_size) private TextView mSizeView; @Inject private ApplicationPreferences mPreferences; @Inject private Provider<Tracker> mTrackerProvider; @Inject private TrackDownloaderFactory mDownloaderFactory; private TrackEntity mTrack; private static String TRACK_TAG = "TRACK_TAG"; private static String ANALYTICS_TAG = "DOWNLOAD_TRACK_FRAGMENT"; public static DownloadTrackFragment newInstance(MediaState state) { final DownloadTrackFragment fragment = new DownloadTrackFragment(); final Bundle args = new Bundle(); // This will raise a loud exception if we have a null, which is fine. args.putParcelable(TRACK_TAG, state.getTrackOption().get()); fragment.setArguments(args); return fragment; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mTrack = getArguments().getParcelable(TRACK_TAG); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.select_track, container, false); } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); if (mPreferences.isAdFree()) { mRemoveAdsButton.setVisibility(View.GONE); } bindButtons(); updateTrackDisplay(); } private void updateTrackDisplay() { if (mTrack == null) { return; } mTitleView.setText(mTrack.getTitle()); mDescriptionView.setText(mTrack.getDescription()); mLengthView.setText(mTrack.getFormattedDuration()); mLengthView.setVisibility(View.VISIBLE); mSizeView.setText(mTrack.getFormattedSize()); mArtistView.setText(mTrack.getUser().getUsername()); mProgressBarView.setVisibility(View.GONE); mDetailContainerView.setVisibility(View.VISIBLE); updateTrackAvailability(); updateButtons(); updateArtwork(); } private void updateArtwork() { // It's from a JSON resource we don't control, so let's be safe. if (mTrack.getArtworkUrl() != null) { Picasso.with(getActivity()).load(mTrack.getArtworkUri()).into(mArtworkImageView); } } private void bindButtons() { mDownloadButton.setOnClickListener(new DownloadButtonClickListener()); mRemoveAdsButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View arg0) { final Intent intent = new Intent(getActivity(), BuyAdFreeActivity.class); startActivity(intent); } }); } /** * Update the button display based on the availability of mTrack. */ private void updateButtons() { if (mTrack.isDownloadable()) { mDownloadButton.setEnabled(true); } else if (mTrack.isPurchasable()) { mDownloadButton.setEnabled(true); final String title = mTrack.getPurchaseTitle(); if (title == null || title.isEmpty()) { mDownloadButton.setText(R.string.lbl_purchase); } else { mDownloadButton.setText(title); } } } /** * Updates UI properties based on the availability of the song. */ private void updateTrackAvailability() { if (!mTrack.isDownloadable()) { mTrackUnavailableView.setVisibility(View.VISIBLE); if (mTrack.isPurchasable()) { Crouton.showText(this.getActivity(), getString(R.string.track_crouton_unavilable_purchase), Style.INFO); mTrackUnavailableView.setText(R.string.track_error_unavailable_purchase); } else { Crouton.showText(this.getActivity(), getString(R.string.track_crouton_unavilable), Style.ALERT); } } } private void downloadTrack(final Uri uri) throws Exception { // Download using TrackDownloader final Handler handler = new Handler(new DownloadHandlerCallback()); final TrackDownloader downloader = mDownloaderFactory.create(uri, mTrack, handler); downloader.enqueue(); Toast.makeText(getActivity(), getString(R.string.toast_download_started), Toast.LENGTH_SHORT).show(); } private class DownloadTask extends RoboAsyncTask<Uri> { @Inject private ServiceManager mServiceManager; private final String mId; protected DownloadTask(final String id) { super(getActivity()); mId = id; } @Override public Uri call() throws Exception { final DownloadService service = mServiceManager.downloadService(); return service.resolveUri(mId); } @Override protected void onSuccess(final Uri t) throws Exception { super.onSuccess(t); Ln.d("Resolved download URL: %s", t); downloadTrack(t); } } private class DownloadHandlerCallback implements Handler.Callback { @Override public boolean handleMessage(final Message msg) { final TrackErrorActivity.ErrorCode errorCode; if (msg.what == TrackDownloader.MSG_DOWNLOAD_STORAGE_ERROR) { errorCode = TrackErrorActivity.ErrorCode.NO_WRITE_PERMISSION; } else { errorCode = TrackErrorActivity.ErrorCode.UNKNOWN_ERROR; } mTrackerProvider.get() .send(new HitBuilders.ExceptionBuilder() .setDescription("Track Download Error") .setFatal(false) .set("WHAT", String.valueOf(msg.what)) .build() ); getContract().handleFatalError(errorCode); return true; } } private class DownloadButtonClickListener implements View.OnClickListener { private void startDownload() { final DownloadTask task = new DownloadTask(String.valueOf(mTrack.getId())); task.execute(); mTrackerProvider.get() .send(new HitBuilders.EventBuilder() .setCategory(ANALYTICS_TAG) .setAction("DOWNLOAD") .setLabel(mTrack.getTitle()) .set("ID", String.valueOf(mTrack.getId())) .build() ); } private void startPurchase() { Uri uri = Uri.parse(mTrack.getPurchaseUrl()); mTrackerProvider.get() .send(new HitBuilders.EventBuilder() .setCategory(ANALYTICS_TAG) .setAction("PURCHASE") .setLabel(mTrack.getTitle()) .set("ID", String.valueOf(mTrack.getId())) .set("URI", uri.toString()) .build() ); final Intent intent = new Intent(Intent.ACTION_VIEW, uri); startActivity(intent); } @Override public void onClick(final View v) { if (mTrack.isDownloadable()) { startDownload(); mDownloadButton.setEnabled(false); } else if (mTrack.isPurchasable()) { startPurchase(); // Keep purchase button enabled. } } } }