/*
* Copyright (c) linroid 2015.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.linroid.pushapp.ui.send;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v4.util.Pair;
import android.text.TextUtils;
import android.text.format.Formatter;
import android.view.Menu;
import android.view.MenuItem;
import com.linroid.pushapp.App;
import com.linroid.pushapp.Constants;
import com.linroid.pushapp.R;
import com.linroid.pushapp.api.PushService;
import com.linroid.pushapp.model.Pack;
import com.linroid.pushapp.model.Push;
import com.linroid.pushapp.ui.base.BaseActivity;
import com.linroid.pushapp.ui.bind.ScanActivity;
import com.linroid.pushapp.ui.device.DeviceFragment;
import com.linroid.pushapp.ui.home.HomeActivity;
import com.linroid.pushapp.util.CountingTypedFile;
import java.io.File;
import java.util.Collections;
import java.util.List;
import javax.inject.Inject;
import butterknife.Bind;
import butterknife.OnClick;
import retrofit.Callback;
import retrofit.RetrofitError;
import retrofit.client.Response;
import retrofit.mime.TypedString;
import rx.Subscriber;
import rx.Subscription;
public class SendActivity extends BaseActivity
implements Callback<Push>, OnSelectCountChangedListener {
public static final String EXTRA_PACKAGE = "package";
public static final String EXTRA_APPLICATION_INFO = "application";
public static final int REQUEST_SEND = 0x9999;
private OnSelectActionListener selectListener;
@Inject
PushService installApi;
@Bind(R.id.fab_complete)
FloatingActionButton fab;
Pack pack;
ApplicationInfo appInfo;
ProgressDialog dialog;
Subscription subscription;
public static Intent createNewSelectIntent(Activity source, Pack pack) {
Intent intent = new Intent(source, SendActivity.class);
intent.putExtra(EXTRA_PACKAGE, pack);
return intent;
}
public static Intent createNewSelectIntent(Activity source, ApplicationInfo info) {
Intent intent = new Intent(source, SendActivity.class);
intent.putExtra(EXTRA_APPLICATION_INFO, info);
return intent;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
if (intent.hasExtra(EXTRA_PACKAGE)) {
this.pack = intent.getParcelableExtra(EXTRA_PACKAGE);
} else if (intent.hasExtra(EXTRA_APPLICATION_INFO)) {
this.appInfo = intent.getParcelableExtra(EXTRA_APPLICATION_INFO);
} else {
throw new IllegalArgumentException("EXTRA_PACKAGE or EXTRA_APPLICATION_INFO extra data required");
}
dialog = new ProgressDialog(this);
dialog.setMessage(getString(R.string.msg_upload_prepare));
dialog.setMax(100);
dialog.setCancelable(false);
dialog.setIndeterminate(true);
getSupportFragmentManager().beginTransaction()
.replace(R.id.container, new DeviceFragment())
.commit();
App.from(this).component().inject(this);
}
public void setSelectListener(OnSelectActionListener selectListener) {
this.selectListener = selectListener;
}
@Override
protected int provideContentViewId() {
return R.layout.activity_select_device;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.select_device, menu);
return true;
}
@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 (this.selectListener != null) {
if (id == R.id.action_select_all) {
selectListener.onSelectAll();
return true;
} else if (id == R.id.action_select_none) {
selectListener.onSelectNone();
return false;
}
}
return super.onOptionsItemSelected(item);
}
@OnClick(R.id.fab_complete)
void onCompleteBtnClicked(final FloatingActionButton btn) {
if (selectListener == null) {
throw new IllegalStateException();
}
if (selectListener.provideSelectedCount()==0) {
Intent intent = ScanActivity.createNewScanIntent(this, getString(R.string.txt_scan_device), Constants.QRCODE_KEY_DEVICE);
startActivityForResult(intent, ScanActivity.REQ_SCAN_QRCODE);
}
List<String> selectedIds = selectListener.provideSelectedDeviceIds();
pushToDevice(selectedIds);
}
private void pushToDevice(List<String> devices) {
if (devices.size() == 0) {
Snackbar.make(fab, R.string.error_not_select_any_device, Snackbar.LENGTH_SHORT).show();
return;
}
Snackbar.make(fab, getString(R.string.msg_push_install_package, devices.size()), Snackbar.LENGTH_SHORT).show();
String deviceIds = TextUtils.join(",", devices.toArray());
if (pack != null) {
installApi.installPackage(deviceIds, pack.getId(), this);
} else {
File apkFile = new File(appInfo.sourceDir);
CountingTypedFile typedFile = new CountingTypedFile(apkFile);
dialog.show();
typedFile.subscribe(new Subscriber<Pair<Long, Long>>() {
@Override
public void onCompleted() {
dialog.setMessage(getString(R.string.msg_upload_complete));
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(Pair<Long, Long> pair) {
dialog.setMessage(getString(R.string.msg_upload_progress,
Formatter.formatShortFileSize(SendActivity.this, pair.second),
Formatter.formatShortFileSize(SendActivity.this, pair.first)));
}
});
installApi.installLocal(new TypedString(deviceIds), typedFile, this);
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode== ScanActivity.REQ_SCAN_QRCODE && resultCode==RESULT_OK) {
String key = data.getStringExtra(ScanActivity.EXTRA_QRCODE_KEY);
String value = data.getStringExtra(ScanActivity.EXTRA_QRCODE_VALUE);
if (!Constants.QRCODE_KEY_DEVICE.equals(key)) {
Snackbar.make(fab, R.string.msg_qrcode_type_require_device, Snackbar.LENGTH_SHORT).show();
return;
}
pushToDevice(Collections.singletonList(value));
}
}
@Override
public void success(Push push, Response response) {
Intent intent = getIntent();
intent.putExtra(HomeActivity.EXTRA_MESSAGE, getString(R.string.msg_push_success));
setResult(RESULT_OK, intent);
dialog.dismiss();
finish();
}
@Override
public void failure(RetrofitError error) {
dialog.dismiss();
Snackbar.make(fab, error.getMessage(), Snackbar.LENGTH_SHORT).show();
}
@Override
public void onDestroy() {
super.onDestroy();
if(subscription!=null && !subscription.isUnsubscribed()) {
subscription.unsubscribe();
}
}
@Override
public void onSelectCountChanged(int prev, int current) {
if (current == 0) {
switchFabIcon(R.drawable.ic_fab_scan);
} else if(prev==0) {
switchFabIcon(R.drawable.ic_fab_complete);
}
}
private void switchFabIcon(final int drawableResId) {
final long duration = getResources().getInteger(android.R.integer.config_shortAnimTime);
fab.animate()
.scaleX(0f)
.scaleY(0f)
.setDuration(duration)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
fab.setImageDrawable(getResources().getDrawable(drawableResId));
fab.animate()
.scaleX(1.f)
.scaleY(1.f)
.setDuration(duration)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
fab.setScaleX(1.f);
fab.setScaleY(1.f);
}
})
.start();
}
})
.start();
}
}