package edu.mit.mitmobile2.about;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.zip.CRC32;
import java.util.zip.Deflater;
import android.content.Context;
import android.content.Intent;
import android.gesture.Gesture;
import android.gesture.GestureLibraries;
import android.gesture.GestureLibrary;
import android.gesture.GestureOverlayView;
import android.gesture.GestureOverlayView.OnGesturePerformedListener;
import android.gesture.Prediction;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;
import android.widget.TextView;
import edu.mit.mitmobile2.CommonActions;
import edu.mit.mitmobile2.NewModule;
import edu.mit.mitmobile2.NewModuleActivity;
import edu.mit.mitmobile2.PrefsActivity;
import edu.mit.mitmobile2.R;
public class AboutActivity extends NewModuleActivity implements OnGesturePerformedListener {
//private static int sSquareSize; // must be an even number
private static final int sSquareSize = 10;
private static BitmapDrawable sBitmap;
private ImageView mAboutImage;
private View mBuildSettingsView;
//private LinearLayout mHeader;
private Context mContext = this;
private GestureLibrary mLibrary;
static final int MENU_HOME = Menu.FIRST;
/****************************************************/
@Override
@SuppressWarnings("static-access")
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.about);
setTitle("About");
TextView tv = (TextView) findViewById(R.id.aboutAppTitle);
tv.setText(this.getResources().getString(R.string.app_name));
tv = (TextView) findViewById(R.id.aboutAppVersion);
tv.setText("v" + Config.VERSION_NAME);
mAboutImage = (ImageView) findViewById(R.id.aboutVersionImage);
if (sBitmap == null) {
sBitmap = getVersionBitmap();
}
mAboutImage.setImageDrawable(sBitmap);
mBuildSettingsView = findViewById(R.id.aboutSettingsList);
tv = (TextView) findViewById(R.id.aboutVersionId);
String buildId = Config.BUILD_ID;
if(buildId.length() > 6) {
buildId = buildId.substring(0, 6);
}
tv.setText("Version: " + buildId);
TextView buildDateTV = (TextView) findViewById(R.id.aboutBuildDate);
buildDateTV.setVisibility(View.GONE);
TextView buildTagTV = (TextView) findViewById(R.id.aboutBuildTag);
buildTagTV.setVisibility(View.GONE);
// buildTagTV.setText("Built for: " + Config.BUILD_TAG);
TextView serverDomainTV = (TextView) findViewById(R.id.aboutServerDomain);
//serverDomainTV.setText("Server: " + Config.MOBILE_WEB_DOMAIN);
serverDomainTV.setText("Server: " + app.getMobileWebDomain());
//mHeader = (LinearLayout) findViewById(R.id.aboutHeader);
//mHeader.setOnClickListener(newListener(true));
mAboutImage.setOnClickListener(newListener(true));
View aboutCreditsTV = findViewById(R.id.aboutCreditsTV);
aboutCreditsTV.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(mContext, AboutCreditsActivity.class);
startActivity(intent);
}
});
View aboutMitTV = findViewById(R.id.aboutMITTV);
aboutMitTV.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(mContext, AboutMITActivity.class);
startActivity(intent);
}
});
View sendFeedback = findViewById(R.id.send_feedback);
sendFeedback.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
CommonActions.composeEmail(mContext, getString(R.string.feedback_email));
}
});
// GESTURE
mLibrary = GestureLibraries.fromRawResource(this, R.raw.gestures);
if (!mLibrary.load()) {
finish();
}
GestureOverlayView gestures = (GestureOverlayView) findViewById(R.id.gestures);
gestures.addOnGesturePerformedListener(this);
// GESTURE
}
private OnClickListener newListener(boolean toggleVersionOn) {
if (toggleVersionOn) {
return new OnClickListener() {
@Override
public void onClick(View v) {
mBuildSettingsView.setVisibility(View.VISIBLE);
mAboutImage.setOnClickListener(newListener(false));
//mHeader.setOnClickListener(newListener(false));
}
};
} else {
return new OnClickListener() {
@Override
public void onClick(View v) {
mBuildSettingsView.setVisibility(View.GONE);
mAboutImage.setOnClickListener(newListener(true));
//mHeader.setOnClickListener(newListener(true));
}
};
}
}
@Override
public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
ArrayList<Prediction> predictions = mLibrary.recognize(gesture);
// We want at least one prediction
if (predictions.size() > 0) {
Prediction prediction = (Prediction)predictions.get(0);
// We want at least some confidence in the result
if (prediction.score > 1.0) {
// Show the selection
startActivity( new Intent(this, PrefsActivity.class) );
//Toast.makeText(this, prediction.name, Toast.LENGTH_SHORT).show();
}
}
}
private BitmapDrawable getVersionBitmap() {
String dirpath = "/data/data/" + Config.release_project_name + "/about";
String buildId = Config.BUILD_ID;
File dir = new File(dirpath);
if (!dir.exists())
dir.mkdir();
String path = dir + "/" + buildId.substring(0, 6) + ".png";
File file = new File(path);
if (!file.exists()) {
for (File oldFile : dir.listFiles()) {
oldFile.delete();
}
//sSquareSize = 2 * (Math.min(display.getWidth(), display.getHeight()) / 36);
int hashLen = 3 * 4 * 4;
while (buildId.length() < hashLen) {
buildId += buildId;
}
buildId = buildId.substring(0, hashLen);
try {
file.createNewFile();
FileOutputStream outStream = new FileOutputStream(file);
// png signature
outStream.write(new byte[] {
(byte)0x89, (byte)0x50, (byte)0x4e, (byte)0x47,
(byte)0x0d, (byte)0x0a, (byte)0x1a, (byte)0x0a
});
// header chunk
ByteBuffer buf = ByteBuffer.allocate(4 + 4 + 5);
buf.put(splitInt(sSquareSize * 4)); // width
buf.put(splitInt(sSquareSize * 4)); //height
buf.put(new byte[] {
(byte)0x04, (byte)0x03, (byte)0x0, (byte)0x0, (byte)0x0}
); // bitdpth, colrtyp, cmprss, fltr, intrlce
writeChunk(outStream, "IHDR", buf.array());
// palette chunk
byte[] palette = new byte[hashLen];
for (int i = 0; i < hashLen; i++) {
// want f(x) s.t. f('0') = 0, f('9') = 9; f('a') = 10, ...
// since ord('0') = 48 and ord('a') = 97 and
// 97 ~ (48 + 10) ~ 9 (mod 39), can use f(x) = ord(x) % 39 - 9
int c = ((int)buildId.charAt(i) % 39 - 9) * 16;
palette[i] = (byte)c;
}
writeChunk(outStream, "PLTE", palette);
// image data chunk
buf = ByteBuffer.allocate(4 * 4 * sSquareSize * sSquareSize + 4 * sSquareSize);
@SuppressWarnings("unused")
int curPos = 0;
for (int bigRow = 0; bigRow < 4; bigRow++) {
for (int smallRow = 0; smallRow < sSquareSize; smallRow++) {
buf.put((byte)0);
for (int bigCol = 0; bigCol < 4; bigCol++) {
for (int smallCol = 0; smallCol < sSquareSize / 2; smallCol++) {
int pixel = (bigRow * 4 + bigCol);
// repeat the same pixel twice in one byte
buf.put((byte)(pixel*16 + pixel));
curPos++;
}
}
}
}
Deflater deflater = new Deflater();
deflater.setInput(buf.array());
deflater.finish();
byte[] zipped = new byte[buf.capacity()];
int numBytes = deflater.deflate(zipped);
buf = ByteBuffer.allocate(numBytes);
buf.put(zipped, 0, numBytes);
byte[] compressed = buf.array();
writeChunk(outStream, "IDAT", compressed);
writeChunk(outStream, "IEND", new byte[0]);
} catch (IOException e) {
e.printStackTrace();
}
}
return new BitmapDrawable(getResources(), path);
}
private byte[] splitInt(long num) {
return new byte[] {
(byte)((num >> 24) & 255), (byte)((num >> 16) & 255),
(byte)((num >> 8) & 255), (byte)(num & 255) };
}
private void writeChunk(FileOutputStream stream, String header, byte[] content) throws IOException {
stream.write(splitInt(content.length));
int len = header.length() + content.length;
ByteBuffer buf = ByteBuffer.allocate(len);
buf.put(new byte[] {
(byte)header.charAt(0), (byte)header.charAt(1),
(byte)header.charAt(2), (byte)header.charAt(3) });
buf.put(content);
CRC32 crc32 = new CRC32();
crc32.update(buf.array(), 0, len);
stream.write(buf.array());
stream.write(splitInt(crc32.getValue()));
}
@Override
protected NewModule getNewModule() {
return new AboutModule();
}
@Override
public boolean isModuleHomeActivity() {
return true;
}
@Override
protected boolean isScrollable() {
return false;
}
@Override
protected void onOptionSelected(String optionId) { }
}