package com.openvehicles.OVMS.ui;
import java.text.SimpleDateFormat;
import android.app.AlertDialog;
import android.app.NotificationManager;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.openvehicles.OVMS.R;
import com.openvehicles.OVMS.api.OnResultCommandListener;
import com.openvehicles.OVMS.entities.CarData;
import com.openvehicles.OVMS.utils.CarsStorage;
import com.openvehicles.OVMS.utils.NotificationData;
import com.openvehicles.OVMS.utils.OVMSNotifications;
public class NotificationsFragment extends BaseFragment
implements OnItemClickListener, TextView.OnEditorActionListener, OnResultCommandListener {
private static final String TAG = "NotificationsFragment";
private ListView mListView;
private OVMSNotifications mNotifications;
private EditText mCmdInput;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
RelativeLayout layout = (RelativeLayout) inflater.inflate(R.layout.fragment_notifications, null);
mListView = (ListView) layout.findViewById(R.id.listView);
mListView.setOnItemClickListener(this);
mCmdInput = (EditText) layout.findViewById(R.id.cmdInput);
mCmdInput.setOnEditorActionListener(this);
return layout;
}
@Override
public void onResume() {
super.onResume();
// cancel Android system notification:
NotificationManager mNotificationManager = (NotificationManager) getActivity()
.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.cancelAll();
// update list:
update();
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
NotificationData data = (NotificationData) parent.getAdapter().getItem(position);
if (data.Type == NotificationData.TYPE_COMMAND) {
// use as history:
mCmdInput.setText(data.Message);
mCmdInput.requestFocus();
mCmdInput.postDelayed(new Runnable() {
@Override
public void run() {
InputMethodManager keyboard = (InputMethodManager)
getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
keyboard.showSoftInput(mCmdInput, 0);
}
},200);
} else {
// display:
Log.d(TAG, "Displaying notification: #" + position);
new AlertDialog.Builder(parent.getContext())
.setIcon(data.getIcon())
.setTitle(data.Title)
.setMessage(data.getMessageFormatted())
.setCancelable(false)
.setPositiveButton(R.string.Close, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
})
.show();
}
}
@Override
public void update(CarData pCarData) {
/* why should we reload notifications on every cardata update?
doesn't seem to be necessary
Context context = getActivity();
if (context != null)
initUi(context);
*/
}
public void update() {
Context context = getActivity();
if (context != null)
initUi(context);
}
private void initUi(Context pContext) {
// (re-)load notifications:
mNotifications = new OVMSNotifications(pContext);
NotificationData[] data = new NotificationData[mNotifications.notifications.size()];
mNotifications.notifications.toArray(data);
// attach array to ListView:
mListView.setAdapter(new ItemsAdapter(pContext, data));
}
@Override
public boolean onEditorAction(TextView textView, int actionId, KeyEvent keyEvent) {
boolean handled = false;
if (actionId == EditorInfo.IME_ACTION_SEND) {
String cmd = textView.getText().toString();
if (cmd.length() > 0) {
// add cmd to notifications:
String vehicle_id = CarsStorage.get().getLastSelectedCarId();
mNotifications.addNotification(
NotificationData.TYPE_COMMAND, vehicle_id + ": " + cmd, cmd);
initUi(getActivity());
// send command:
if (cmd.matches("[0-9*#]+"))
sendCommand(cmd, "41," + cmd, this); // MMI/USSD command
else
sendCommand(cmd, "7," + cmd, this); // SMS command
handled = true;
}
}
return handled;
}
@Override
public void onResultCommand(String[] result) {
if (result.length <= 1)
return;
int command = Integer.parseInt(result[0]);
String cmdMessage = getSentCommandMessage(result[0]);
int resCode = Integer.parseInt(result[1]);
if (command != 7 && command != 41)
return; // not for us
String cmdOutput = null;
if (result.length >= 3 && result[2] != null)
cmdOutput = result[2];
String vehicle_id = CarsStorage.get().getLastSelectedCarId();
switch (resCode) {
case 0: // ok: result[2] = command output
int type = (command == 41) ? NotificationData.TYPE_USSD
: NotificationData.TYPE_RESULT_SUCCESS;
// suppress first (empty) OK result for cmd 41:
if (command == 7 || cmdOutput != null) {
mNotifications.addNotification(
type, vehicle_id + ": " + cmdMessage,
(cmdOutput != null) ? cmdOutput : getString(R.string.msg_ok));
initUi(getActivity());
}
break;
case 1: // failed: result[2] = command output
mNotifications.addNotification(
NotificationData.TYPE_RESULT_ERROR, vehicle_id + ": " + cmdMessage,
getString(R.string.err_failed_smscmd));
initUi(getActivity());
break;
case 2: // unsupported
Toast.makeText(getActivity(), cmdMessage + " => " + getString(R.string.err_unsupported_operation),
Toast.LENGTH_SHORT).show();
break;
case 3: // unimplemented
Toast.makeText(getActivity(), cmdMessage + " => " + getString(R.string.err_unimplemented_operation),
Toast.LENGTH_SHORT).show();
break;
}
}
private static class ItemsAdapter extends ArrayAdapter<NotificationData> {
private final LayoutInflater mInflater;
private final SimpleDateFormat mDateFormat = new SimpleDateFormat("MMM d, HH:mm");
public ItemsAdapter(Context context, NotificationData[] items) {
super(context, R.layout.item_notifications, items);
mInflater = LayoutInflater.from(context);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
v = mInflater.inflate(R.layout.item_notifications, null);
}
NotificationData it = getItem(position);
if (it != null) {
// set icon according to notification type:
ImageView iv = (ImageView) v.findViewById(R.id.textNotificationsIcon);
iv.setImageResource(it.getIcon());
// set title, message & timestamp:
TextView tv = (TextView) v.findViewById(R.id.textNotificationsListTitle);
tv.setText(it.Title);
tv = (TextView) v.findViewById(R.id.textNotificationsListMessage);
if (it.Type == NotificationData.TYPE_COMMAND) {
tv.setVisibility(View.GONE); // cmd shown in title
} else {
tv.setVisibility(View.VISIBLE);
tv.setText(it.getMessageFormatted());
}
tv = (TextView) v.findViewById(R.id.textNotificationsListTimestamp);
tv.setText(mDateFormat.format(it.Timestamp));
}
return v;
}
}
}