I am currently working on an app in which one of the tasks is to catch the notifications of different applications (phone call, Facebook, Twitter, Whatsapp etc...). Now I will have some values pre-defined for all the pre-defined applications. Values will be of type string denoting R,G,B color values. I would have to send these color values via Bluetooth to another device. For this I have created an accessibility service.
Here is my main activity:
Main Activity displays a listview with applications name declared in the currentlyEnabled
HashMap
. The newFinalPackages
HashMap
stores the application names for all the pre defined applications. The apptoRBG
HashMap
stores these application names with user-given RGB values.
public class MainActivity extends AppCompatActivity {
private Intent mailAccessabilityIntent;
private ListView actioList;
private ActionCustomAdapter adapter;
private static final String DEFAULT_COLOR = "R:255,G:255,B:255";
private static HashMap<String, String> newfinalpackages = new HashMap<String, String>();
private static HashMap<String, String> newappToRGB = new HashMap<String, String>();
static {
newfinalpackages.put("dialer", "Calls");
newfinalpackages.put("whatsapp", "WhatsApp");
newfinalpackages.put("facebook.katana", "Facebook");
newfinalpackages.put("twitter", "Twitter");
newfinalpackages.put("instagram", "Instagram");
newfinalpackages.put("gmail", "GMail");
newfinalpackages.put("batterylow", "Low Battery");
newfinalpackages.put("messenger", "Text Message");
newappToRGB.put("dialer", DEFAULT_COLOR);
newappToRGB.put("whatsapp", DEFAULT_COLOR);
newappToRGB.put("facebook", DEFAULT_COLOR);
newappToRGB.put("twitter", DEFAULT_COLOR);
newappToRGB.put("instagram", DEFAULT_COLOR);
newappToRGB.put("gmail", null);
newappToRGB.put("batterylow", null);
newappToRGB.put("messenger", null);
}
private static HashMap<String, String> currentlyEnabled = new HashMap<String, String>();
private HashMap<String, String> currentlyDisabled = new HashMap<String, String>();
public static HashMap<String, String> getCurrentlyEnabled() {
return currentlyEnabled;
}
public static HashMap<String, String> getAppToRGB() {
return newappToRGB;
}
private void DrawSelected() {
currentlyEnabled.put("dialer", "Calls");
currentlyEnabled.put("whatsapp", "WhatsApp");
currentlyEnabled.put("facebook", "Facebook");
currentlyEnabled.put("twitter", "Twitter");
currentlyEnabled.put("instagram", "Instagram");
currentlyDisabled.put("gmail", "GMail");
currentlyDisabled.put("batterylow", "Low Battery");
currentlyDisabled.put("messenger", "Text Message");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent mailAccess = new Intent(MainActivity.this, InstantMessanger.class);
startService(mailAccess);
DrawSelected();
serviceSwitch = (Switch) findViewById(R.id.serviceSwitch); //DIDN'T ADD FUNCTIONALITY YET.
actioList = (ListView) findViewById(R.id.actionList);
// Button to add applications from currentlyDisabled to CurrentlyEnabled
// Not Important here.
actioList.addFooterView(addEvent);
adapter = new ActionCustomAdapter(this, currentlyEnabled);
actioList.setAdapter(adapter);
// Just to choose the color value.Nothing Else.
actioList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
String Item = ((HashMap.Entry<String, String>) adapterView.getItemAtPosition(i)).getKey();
showColorPickerDialogDemo(Item);
}
});
}
// IGNORE THIS.
private void showColorPickerDialogDemo(final String key) {
int initialColor = Color.WHITE;
ColorPickerDialog colorPickerDialog = new ColorPickerDialog(this, initialColor, new ColorPickerDialog.OnColorSelectedListener() {
@Override
public void onColorSelected(int color) {
showToast(color);
appToRGB.put(key, "R: " + Color.red(color) + " B: " + Color.blue(color) + " G: " + Color.green(color));
InstantMessanger.addEnabledActions(key, "R: " + Color.red(color) + " B: " + Color.blue(color) + " G: " + Color.green(color));
}
});
colorPickerDialog.show();
}
@Override
protected void onDestroy() {
super.onDestroy();
}
}
showColorPickerDemo()
is for color selection.
My service class is:
When created, the enabledAction
HashMap
from MainActivity
is passed to this class using static methods.
The service class basically catches any notification posted on an Android device by any application with the listener OnAccessibility
event. Then it is extracting the actual application name from the package name in the parsePackage()
method. Then it checks if this application name is in enabledActions
. If yes, it sends the data through Bluetooth (which still needs to be implemented).
public class InstantMessanger extends AccessibilityService {
private TextView text;
private String packagename;
private String selfname = "com.example.sgoel01.checkingevents",download = "com.android.providers.downloads";
Context context = this;
private static HashMap<String,String> enabledActions = new HashMap<String, String>();
public static void addEnabledActions(String key, String value) {
enabledActions.put(key, value);
}
@Override
public void onCreate() {
Toast.makeText(this, "Service is Started for the first time", Toast.LENGTH_LONG).show();
enabledActions = MainActivity.getAppToRGB();
for(HashMap.Entry<String,String> entry : enabledActions.entrySet()) {
Log.d("enabledAct", entry.getKey() + " is equal to " + entry.getValue());
}
Toast.makeText(this, enabledActions.get("whatsapp"), Toast.LENGTH_SHORT).show();
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "Service is Started on startcommand", Toast.LENGTH_LONG).show();
enabledActions = MainActivity.getAppToRGB();
return Service.START_STICKY;
}
public void onAccessibilityEvent(AccessibilityEvent event) {
//Toast.makeText(this,"Event Catched", Toast.LENGTH_LONG).show();
if(event.getEventType() == AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED) {
packagename = String.valueOf(event.getPackageName());
Log.d("pack/call", packagename);
parsePackage(packagename);
if(packagename.equals(selfname)==false && packagename.equals("com.android.providers.downloads")==false) {
Toast.makeText(this, "Package: "+packagename,Toast.LENGTH_LONG).show();
}
if(enabledActions.get(packagename) != null) {
Toast.makeText(this, "This is Working Now " + packagename , Toast.LENGTH_LONG).show();
}
}
}
private void parsePackage (String pack) {
String name = pack.substring(pack.indexOf(".")+1,pack.length());
char[] array = pack.toCharArray();
int prev=0;
for(int i=0,n=pack.length() ; i<n ; i++) {
String temp="";
if(i==n-1) {
temp = pack.substring(prev,i+1);
Log.d("seetothis", "Name: " + temp +" has value= " + enabledActions.get(temp) );
}
else if(pack.charAt(i) == '.') {
temp = pack.substring(prev,i);
prev = i+1;
Log.d("seetothis", "Name: " + temp +" has value= " + enabledActions.get(temp) );
}
if(enabledActions.get(temp) != null) {
Log.d("printout", "Package grabbed is: "+temp+" With Value: "+enabledActions.get(temp));
}
}
}
@Override
public void onInterrupt() {
}
public static String gettheColor() {
return enabledActions.get("dialer");
}
@Override
public void onDestroy() {
Toast.makeText(this, "hUA Nhi ",Toast.LENGTH_SHORT).show();
super.onDestroy();
}
@Override
protected void onServiceConnected() {
AccessibilityServiceInfo info = new AccessibilityServiceInfo();
info.feedbackType = 1;
info.eventTypes = AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED;
info.notificationTimeout = 100;
setServiceInfo(info);
}
}
Here is my custom adapter for listview on main activity. This is taking the HashMap
s and simply displaying in listview.
public class ActionCustomAdapter extends BaseAdapter {
private Activity activity;
private ArrayList mData;
private static LayoutInflater inflater=null;
public ActionCustomAdapter(Activity a, HashMap<String,String> d) {
activity = a;
mData = new ArrayList();
mData.addAll(d.entrySet());
inflater = (LayoutInflater)activity.
getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public int getCount() {
return mData.size();
}
@Override
public HashMap.Entry<String, String> getItem(int position) {
return (HashMap.Entry) mData.get(position);
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
View vi=convertView;
if(convertView==null)
vi = inflater.inflate(R.layout.list_item_notification, null);
HashMap.Entry<String, String> item = getItem(position);
TextView text=(TextView)vi.findViewById(R.id.textAction);;
ImageView image=(ImageView)vi.findViewById(R.id.imageAction);
text.setText(item.getValue());
return vi;
}
}
Am I declaring too many static methods and variables? Am I passing too much data between the activities?
Also, my service intend to run in the background, so do I need a different set of variables (corresponding string values for different applications) for it always, or can I just extract them from another activity whenever required? Or there is some better way?