package com.felkertech.cumulustv.activities;
import android.Manifest;
import android.app.Activity;
import android.content.ComponentName;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.drawable.ColorDrawable;
import android.media.tv.TvContract;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import com.crashlytics.android.Crashlytics;
import com.felkertech.cumulustv.fileio.CloudStorageProvider;
import com.felkertech.cumulustv.model.ChannelDatabase;
import com.felkertech.cumulustv.model.JsonChannel;
import com.felkertech.cumulustv.services.CumulusJobService;
import com.felkertech.cumulustv.tv.activities.LeanbackActivity;
import com.felkertech.cumulustv.utils.ActivityUtils;
import com.felkertech.cumulustv.utils.AppUtils;
import com.felkertech.cumulustv.utils.DriveSettingsManager;
import com.felkertech.cumulustv.widgets.ChannelShortcut;
import com.felkertech.n.cumulustv.R;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.drive.Drive;
import com.google.android.gms.drive.DriveApi;
import com.google.android.gms.drive.MetadataChangeSet;
import org.json.JSONException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import io.fabric.sdk.android.Fabric;
import static android.content.pm.PackageManager.PERMISSION_DENIED;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
public class MainActivity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
private static final String TAG = MainActivity.class.getSimpleName();
private static final boolean DEBUG = false;
private static final int RESOLVE_CONNECTION_REQUEST_CODE = 100;
private static final int REQUEST_CODE_CREATOR = 102;
private DriveSettingsManager sm;
private AlertDialog md;
private AlertDialog.OnClickListener genreSelectionCallback = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
}
};
@Override
protected void onResume() {
super.onResume();
ChannelShortcut.updateWidgets(this, ChannelShortcut.class);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(TAG, "onCreate");
sm = new DriveSettingsManager(this);
ActivityUtils.openIntroIfNeeded(this);
CloudStorageProvider.getInstance().autoConnect(this);
try {
final ChannelDatabase channelDatabase = ChannelDatabase.getInstance(MainActivity.this);
Fabric.with(this, new Crashlytics());
if(AppUtils.isTV(this)) {
// Go to tv activity
Intent leanbackIntent = new Intent(this, LeanbackActivity.class);
leanbackIntent.setFlags(Intent.FLAG_ACTIVITY_TASK_ON_HOME);
startActivity(leanbackIntent);
}
updateUi();
} catch (ChannelDatabase.MalformedChannelDataException e) {
ActivityUtils.handleMalformedChannelData(MainActivity.this,
CloudStorageProvider.getInstance().getClient(), e);
}
}
public void updateUi() {
final ChannelDatabase channelDatabase = ChannelDatabase.getInstance(MainActivity.this);
findViewById(R.id.view).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String[] channelnames = channelDatabase.getChannelNames();
if(channelnames.length == 0) {
new AlertDialog.Builder(MainActivity.this)
.setTitle(R.string.no_channels)
.setMessage(R.string.no_channels_find)
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.cancel();
ActivityUtils.openSuggestedChannels(MainActivity.this,
CloudStorageProvider.getInstance().getClient());
}
})
.setNegativeButton(R.string.no, null)
.show();
} else {
try {
displayChannelPicker(channelDatabase.getJsonChannels(), channelnames);
} catch (JSONException e) {
e.printStackTrace();
}
}
}
});
findViewById(R.id.view_genres).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// Generate genres
Set<String> genreSet = new HashSet<>();
try {
for (JsonChannel jsonChannel : channelDatabase.getJsonChannels()) {
Collections.addAll(genreSet, jsonChannel.getGenres());
}
final String[] genreArray = genreSet.toArray(new String[genreSet.size()]);
new AlertDialog.Builder(MainActivity.this)
.setTitle(R.string.select_genres)
.setItems(genreArray, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int position) {
// Now only get certain channels
String selectedGenre = genreArray[position];
List<JsonChannel> jsonChannelList = new ArrayList<>();
List<String> channelNames = new ArrayList<>();
try {
for (JsonChannel jsonChannel :
channelDatabase.getJsonChannels()) {
if (jsonChannel.getGenresString() != null
&& jsonChannel.getGenresString()
.contains(selectedGenre)) {
jsonChannelList.add(jsonChannel);
channelNames.add(jsonChannel.getNumber() + " " +
jsonChannel.getName());
}
}
displayChannelPicker(jsonChannelList, channelNames
.toArray(new String[channelNames.size()]),
selectedGenre);
} catch (JSONException e) {
e.printStackTrace();
}
}
})
.show();
} catch (JSONException e) {
e.printStackTrace();
}
}
});
findViewById(R.id.gdrive).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
CloudStorageProvider.getInstance().connect(MainActivity.this);
}
});
findViewById(R.id.more_actions).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
moreClick();
}
});
}
@Override
public void onConnected(Bundle bundle) {
ActivityUtils.onConnected(CloudStorageProvider.getInstance().getClient());
Log.d(TAG, "onConnected");
if(md != null) {
if(md.isShowing()) {
try {
md.dismiss();
} catch(Exception e) {
e.printStackTrace();
}
}
}
CloudStorageProvider.getInstance().onConnected(Activity.RESULT_OK);
sm.setGoogleDriveSyncable(CloudStorageProvider.getInstance().getClient(), new DriveSettingsManager.GoogleDriveListener() {
@Override
public void onActionFinished(boolean cloudToLocal) {
Log.d(TAG, "Sync req after drive action");
final String info = TvContract.buildInputId(ActivityUtils.TV_INPUT_SERVICE);
CumulusJobService.requestImmediateSync1(MainActivity.this, info, CumulusJobService.DEFAULT_IMMEDIATE_EPG_DURATION_MILLIS,
new ComponentName(MainActivity.this, CumulusJobService.class));
if (cloudToLocal) {
Toast.makeText(MainActivity.this, R.string.downloaded, Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(MainActivity.this, R.string.uploaded, Toast.LENGTH_SHORT).show();
}
}
}); //Enable GDrive
if (DEBUG) {
Log.d(TAG, sm.getString(R.string.sm_google_drive_id) + "<< for onConnected");
}
if(sm.getString(R.string.sm_google_drive_id).isEmpty()) {
// We need a new file
new AlertDialog.Builder(MainActivity.this)
.setTitle(R.string.create_syncable_file)
.setMessage(R.string.create_syncable_file_description)
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Drive.DriveApi.newDriveContents(ActivityUtils.getGoogleApiClient())
.setResultCallback(driveContentsCallback);
}
})
.setNegativeButton(R.string.no, null)
.show();
} else {
//Great, user already has sync enabled, let's resync
ActivityUtils.readDriveData(MainActivity.this, ActivityUtils.getGoogleApiClient());
}
}
@Override
protected void onStart() {
super.onStart();
CloudStorageProvider.getInstance().autoConnect(this);
Log.d(TAG, "onStart");
try {
PackageInfo pInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
((TextView) findViewById(R.id.version)).setText(getString(R.string.version, pInfo.versionName));
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
}
@Override
public void onConnectionSuspended(int i) {
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
if (DEBUG) {
Log.d(TAG, "Error connecting " + connectionResult.getErrorCode());
}
if(md != null) {
if (md.isShowing()) {
Toast.makeText(this, "Error connecting: " + connectionResult.toString(),
Toast.LENGTH_SHORT).show();
}
}
Toast.makeText(MainActivity.this, "Connection issue (" + connectionResult.getErrorCode() +
"): " + connectionResult.toString(), Toast.LENGTH_SHORT).show();
if (DEBUG) {
Log.d(TAG, "oCF " + connectionResult.toString());
}
if (connectionResult.hasResolution()) {
try {
connectionResult.startResolutionForResult(this, RESOLVE_CONNECTION_REQUEST_CODE);
} catch (IntentSender.SendIntentException e) {
// Unable to resolve, message user appropriately
Toast.makeText(MainActivity.this, "Cannot resolve issue", Toast.LENGTH_SHORT).show();
}
} else {
try {
GooglePlayServicesUtil.getErrorDialog(connectionResult.getErrorCode(),
MainActivity.this, 0).show();
} catch(Exception e) {
e.printStackTrace();
}
}
}
@Override
protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
ActivityUtils.onActivityResult(MainActivity.this,
CloudStorageProvider.getInstance().getClient(), requestCode, resultCode, data);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case ActivityUtils.PERMISSION_EXPORT_M3U:
if (grantResults[0] == PERMISSION_GRANTED) {
ActivityUtils.exportM3uPlaylist(MainActivity.this);
}
break;
}
}
/** GDRIVE **/
ResultCallback<DriveApi.DriveContentsResult> driveContentsCallback =
new ResultCallback<DriveApi.DriveContentsResult>() {
@Override
public void onResult(DriveApi.DriveContentsResult result) {
MetadataChangeSet metadataChangeSet = new MetadataChangeSet.Builder()
.setTitle("cumulustv_channels.json")
.setDescription("JSON list of channels that can be imported using " +
"CumulusTV to view live streams")
.setMimeType("application/json").build();
IntentSender intentSender = Drive.DriveApi
.newCreateFileActivityBuilder()
.setActivityTitle("cumulustv_channels.json")
.setInitialMetadata(metadataChangeSet)
.setInitialDriveContents(result.getDriveContents())
.build(CloudStorageProvider.getInstance().getClient());
try {
startIntentSenderForResult(
intentSender, REQUEST_CODE_CREATOR, null, 0, 0, 0);
} catch (IntentSender.SendIntentException e) {
Log.w(TAG, "Unable to send intent", e);
}
}
};
public void moreClick() {
String[] actions = new String[] {
getString(R.string.settings_browse_plugins),
getString(R.string.export_m3u),
getString(R.string.settings_refresh_cloud_local),
};
new AlertDialog.Builder(this)
.setTitle(R.string.more_actions)
.setItems(actions, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
switch (i) {
case 0:
ActivityUtils.browsePlugins(MainActivity.this);
break;
case 1: // Export data as M3u
if (Build.VERSION.SDK_INT >= 23) {
// Check if we're allowed to do this
if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
== PERMISSION_DENIED) {
requestPermissions(new String[]
{Manifest.permission.WRITE_EXTERNAL_STORAGE},
ActivityUtils.PERMISSION_EXPORT_M3U);
break;
}
}
ActivityUtils.exportM3uPlaylist(MainActivity.this);
break;
case 2:
ActivityUtils.readDriveData(MainActivity.this,
CloudStorageProvider.getInstance().getClient());
break;
case 7:
new AlertDialog.Builder(MainActivity.this)
.setTitle(R.string.about_mlc)
.setMessage(R.string.about_mlc_summary)
.setPositiveButton(R.string.about_mlc_issues, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Intent gi = new Intent(Intent.ACTION_VIEW);
gi.setData(Uri.parse("https://bitbucket.org/fleke" +
"r/mlc-music-live-channels"));
startActivity(gi);
}
})
.show();
}
}
})
.show();
}
public void displayChannelPicker(final List<JsonChannel> jsonChannels, String[] channelNames) {
displayChannelPicker(jsonChannels, channelNames, getString(R.string.my_channels));
}
public void displayChannelPicker(final List<JsonChannel> jsonChannels, String[] channelNames,
String label) {
new AlertDialog.Builder(MainActivity.this)
.setTitle(label)
.setItems(channelNames, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
JsonChannel jsonChannel = jsonChannels.get(i);
ActivityUtils.editChannel(MainActivity.this, jsonChannel.getMediaUrl());
}
})
.show();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main_mobile, menu);
getSupportActionBar().show();
getSupportActionBar().setBackgroundDrawable(
new ColorDrawable(getResources().getColor(R.color.colorPrimary)));
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_add:
ActivityUtils.openPluginPicker(true, MainActivity.this);
break;
case R.id.menu_add_suggested:
ActivityUtils.openSuggestedChannels(MainActivity.this,
CloudStorageProvider.getInstance().getClient());
break;
case R.id.menu_import:
ActivityUtils.switchGoogleDrive(MainActivity.this,
CloudStorageProvider.getInstance().getClient());
break;
case R.id.menu_licenses:
ActivityUtils.oslClick(MainActivity.this);
break;
case R.id.menu_reset_data:
ActivityUtils.deleteChannelData(MainActivity.this,
CloudStorageProvider.getInstance().getClient());
break;
case R.id.menu_about:
ActivityUtils.openAbout(MainActivity.this);
break;
case R.id.menu_settings:
startActivity(new Intent(this, SettingsActivity.class));
break;
}
return super.onOptionsItemSelected(item);
}
}