Java tutorial
/* * Copyright (c) 2016 ? (OHMAE Ryosuke) * * This software is released under the MIT License. * http://opensource.org/licenses/MIT */ package net.mm2d.dmsexplorer; import android.content.Context; import android.content.res.ColorStateList; import android.graphics.Color; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.design.widget.FloatingActionButton; import android.support.design.widget.Snackbar; import android.support.v4.app.Fragment; import android.support.v4.content.ContextCompat; import android.support.v7.widget.RecyclerView; import android.text.TextUtils; import android.text.format.DateFormat; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import net.mm2d.android.cds.CdsObject; import net.mm2d.android.cds.MediaServer; import net.mm2d.android.cds.Tag; import net.mm2d.android.util.AribUtils; import net.mm2d.android.util.LaunchUtils; import net.mm2d.util.Log; import java.io.UnsupportedEncodingException; import java.util.Date; import java.util.List; import java.util.Locale; /** * CDS??Fragment * * @author <a href="mailto:ryo@mm2d.net">?(OHMAE Ryosuke)</a> */ public class CdsDetailFragment extends Fragment implements PropertyAdapter.OnItemLinkClickListener { private static final String TAG = "CdsDetailFragment"; /** * ?? * * <p>Bundle?????????? * * @param udn ???UDN * @param object ?Object * @return */ public static CdsDetailFragment newInstance(String udn, CdsObject object) { final CdsDetailFragment instance = new CdsDetailFragment(); final Bundle arguments = new Bundle(); arguments.putString(Const.EXTRA_UDN, udn); arguments.putParcelable(Const.EXTRA_OBJECT, object); instance.setArguments(arguments); return instance; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { final View rootView = inflater.inflate(R.layout.frg_cds_detail, container, false); final String udn = getArguments().getString(Const.EXTRA_UDN); final MediaServer server = DataHolder.getInstance().getMsControlPoint().getMediaServer(udn); final CdsObject object = getArguments().getParcelable(Const.EXTRA_OBJECT); if (object == null || server == null) { getActivity().finish(); return rootView; } final TextView titleView = (TextView) rootView.findViewById(R.id.title); if (titleView != null) { final String title = object.getTitle(); titleView.setText(AribUtils.toDisplayableString(title)); titleView.setBackgroundColor(ThemeUtils.getAccentColor(title)); } final RecyclerView recyclerView = (RecyclerView) rootView.findViewById(R.id.cds_detail); final PropertyAdapter adapter = new PropertyAdapter(getContext()); adapter.setOnItemLinkClickListener(this); setupPropertyAdapter(getActivity(), adapter, object); recyclerView.setAdapter(adapter); setupFloatingActionButton(rootView, object); return rootView; } private void setupFloatingActionButton(View rootView, final CdsObject object) { FloatingActionButton fab = (FloatingActionButton) rootView.findViewById(R.id.fab); if (fab == null) { fab = (FloatingActionButton) getActivity().findViewById(R.id.fab); } if (fab == null) { return; } fab.setVisibility(hasResource(object) ? View.VISIBLE : View.GONE); final boolean protectedResource = hasProtectedResource(object); final int color = protectedResource ? Color.GRAY : ContextCompat.getColor(getContext(), R.color.accent); fab.setBackgroundTintList(ColorStateList.valueOf(color)); fab.setOnClickListener(view -> { if (protectedResource) { Snackbar.make(view, R.string.toast_not_support_drm, Snackbar.LENGTH_LONG).show(); } else { final SelectResourceDialog dialog = SelectResourceDialog.newInstance(object); dialog.show(getActivity().getFragmentManager(), ""); } }); } private static boolean hasResource(CdsObject object) { return object.getTagList(CdsObject.RES) != null; } private static boolean hasProtectedResource(CdsObject object) { final List<Tag> tagList = object.getTagList(CdsObject.RES); if (tagList == null) { return false; } for (final Tag tag : tagList) { final String protocolInfo = tag.getAttribute(CdsObject.PROTOCOL_INFO); final String mimeType = CdsObject.extractMimeTypeFromProtocolInfo(protocolInfo); if (!TextUtils.isEmpty(mimeType) && mimeType.equals("application/x-dtcp1")) { return true; } } return false; } @Override public void onItemLinkClick(String link) { LaunchUtils.openUri(getContext(), link); } private static String sTb; private static String sBs; private static String sCs; // ???????????? private static void setupString(Context context) { if (sTb != null) { return; } sTb = context.getString(R.string.network_tb); sBs = context.getString(R.string.network_bs); sCs = context.getString(R.string.network_cs); } static void setupPropertyAdapter(@NonNull Context context, @NonNull PropertyAdapter adapter, @NonNull CdsObject object) { Log.d(TAG, object.toDumpString()); setupString(context); adapter.addEntry(context.getString(R.string.prop_title), AribUtils.toDisplayableString(object.getTitle())); adapter.addEntry(context.getString(R.string.prop_channel), getChannel(object)); adapter.addEntry(context.getString(R.string.prop_date), getDate(object)); adapter.addEntry(context.getString(R.string.prop_schedule), getSchedule(object)); adapter.addEntry(context.getString(R.string.prop_genre), object.getValue(CdsObject.UPNP_GENRE)); adapter.addEntry(context.getString(R.string.prop_album), object.getValue(CdsObject.UPNP_ALBUM)); adapter.addEntry(context.getString(R.string.prop_artist), jointMembers(object, CdsObject.UPNP_ARTIST)); adapter.addEntry(context.getString(R.string.prop_actor), jointMembers(object, CdsObject.UPNP_ACTOR)); adapter.addEntry(context.getString(R.string.prop_author), jointMembers(object, CdsObject.UPNP_AUTHOR)); adapter.addEntry(context.getString(R.string.prop_creator), object.getValue(CdsObject.DC_CREATOR)); adapter.addEntry(context.getString(R.string.prop_description), jointTagValue(object, CdsObject.DC_DESCRIPTION)); adapter.addEntryAutoLink(context.getString(R.string.prop_long_description), jointLongDescription(object)); adapter.addEntry(CdsObject.UPNP_CLASS + ":", object.getUpnpClass()); } @Nullable private static String jointTagValue(@NonNull CdsObject object, String tagName) { final List<Tag> tagList = object.getTagList(tagName); if (tagList == null) { return null; } final StringBuilder sb = new StringBuilder(); for (final Tag tag : tagList) { if (sb.length() != 0) { sb.append('\n'); } sb.append(tag.getValue()); } return AribUtils.toDisplayableString(sb.toString()); } @Nullable private static String jointLongDescription(@NonNull CdsObject object) { final List<Tag> tagList = object.getTagList(CdsObject.ARIB_LONG_DESCRIPTION); if (tagList == null) { return null; } try { final StringBuilder sb = new StringBuilder(); for (final Tag tag : tagList) { if (sb.length() != 0) { sb.append('\n'); sb.append('\n'); } final String value = tag.getValue(); if (TextUtils.isEmpty(value)) { continue; } final byte[] bytes = value.getBytes("UTF-8"); final int length = Math.min(24, bytes.length); final String title = new String(bytes, 0, length, "UTF-8"); sb.append(title.trim()); if (value.length() > title.length()) { sb.append('\n'); sb.append(value.substring(title.length())); } } return AribUtils.toDisplayableString(sb.toString()); } catch (final UnsupportedEncodingException ignored) { } return null; } @Nullable private static String jointMembers(@NonNull CdsObject object, String tagName) { final List<Tag> tagList = object.getTagList(tagName); if (tagList == null) { return null; } final StringBuilder sb = new StringBuilder(); for (final Tag tag : tagList) { if (sb.length() != 0) { sb.append('\n'); } sb.append(tag.getValue()); final String role = tag.getAttribute("role"); if (role != null) { sb.append(" : "); sb.append(role); } } return sb.toString(); } @Nullable private static String getChannel(@NonNull CdsObject object) { final StringBuilder sb = new StringBuilder(); final String network = getNetworkString(object); if (network != null) { sb.append(network); } final String channelNr = object.getValue(CdsObject.UPNP_CHANNEL_NR); if (channelNr != null) { if (sb.length() == 0) { sb.append(channelNr); } else { try { final int channel = Integer.parseInt(channelNr); final String nr = String.format(Locale.US, "%1$06d", channel); sb.append(nr.substring(2, 5)); } catch (final NumberFormatException ignored) { } } } final String name = object.getValue(CdsObject.UPNP_CHANNEL_NAME); if (name != null) { if (sb.length() != 0) { sb.append(" "); } sb.append(name); } return sb.length() == 0 ? null : sb.toString(); } @Nullable private static String getNetworkString(@NonNull CdsObject object) { final String net = object.getValue(CdsObject.ARIB_OBJECT_TYPE); if (net == null) { return null; } switch (net) { case "ARIB_TB": return sTb; case "ARIB_BS": return sBs; case "ARIB_CS": return sCs; default: return null; } } @Nullable private static String getDate(@NonNull CdsObject object) { final String str = object.getValue(CdsObject.DC_DATE); final Date date = CdsObject.parseDate(str); if (date == null) { return null; } if (str.length() <= 10) { return DateFormat.format("yyyy/MM/dd (E)", date).toString(); } return DateFormat.format("yyyy/M/d (E) kk:mm:ss", date).toString(); } @Nullable private static String getSchedule(@NonNull CdsObject object) { final Date start = object.getDateValue(CdsObject.UPNP_SCHEDULED_START_TIME); final Date end = object.getDateValue(CdsObject.UPNP_SCHEDULED_END_TIME); if (start == null || end == null) { return null; } final String startString = DateFormat.format("yyyy/M/d (E) kk:mm", start).toString(); final String endString; if (end.getTime() - start.getTime() > 12 * 3600 * 1000) { endString = DateFormat.format("yyyy/M/d (E) kk:mm", end).toString(); } else { endString = DateFormat.format("kk:mm", end).toString(); } return startString + " " + endString; } }