CursorTreeAdapter with search implementation - Java for Android App Development

I make an application for Android and I'm using CursorTreeAdapter as ExpandableListView. Now I want to use search box for display the filtered ExpandableListView items. Like this:
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
Here's the code what I've so far:
MainActivity.java:
Code:
package com.example.android.exlistexample;
import java.util.HashMap;
import android.app.SearchManager;
import android.content.Context;
import android.database.ContentObserver;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.LoaderManager;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.util.Log;
import android.widget.ExpandableListView;
import android.widget.SearchView;
import android.widget.SearchView.OnCloseListener;
import android.widget.SearchView.OnQueryTextListener;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.example.android.exlistexample.provider.CfpContract;
public class MainActivity extends SherlockFragmentActivity {
private SearchView search;
private MyListAdapter listAdapter;
private ExpandableListView myList;
private final String DEBUG_TAG = getClass().getSimpleName().toString();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
search = (SearchView) findViewById(R.id.search);
search.setSearchableInfo(searchManager
.getSearchableInfo(getComponentName()));
search.setIconifiedByDefault(false);
search.setOnQueryTextListener(new OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
listAdapter.filterData(query);
expandAll();
return false;
}
@Override
public boolean onQueryTextChange(String query) {
listAdapter.filterData(query);
expandAll();
return false;
}
});
search.setOnCloseListener(new OnCloseListener() {
@Override
public boolean onClose() {
listAdapter.filterData("");
expandAll();
return false;
}
});
// get reference to the ExpandableListView
myList = (ExpandableListView) findViewById(R.id.expandableList);
// create the adapter
listAdapter = new MyListAdapter(null, MainActivity.this);
// attach the adapter to the list
myList.setAdapter(listAdapter);
Loader<Cursor> loader = getSupportLoaderManager().getLoader(-1);
if (loader != null && !loader.isReset()) {
runOnUiThread(new Runnable() {
public void run() {
getSupportLoaderManager().restartLoader(-1, null,
mSpeakersLoaderCallback);
}
});
} else {
runOnUiThread(new Runnable() {
public void run() {
getSupportLoaderManager().initLoader(-1, null,
mSpeakersLoaderCallback).forceLoad();
;
}
});
}
}
@Override
public void onResume() {
super.onResume();
getApplicationContext().getContentResolver().registerContentObserver(
CfpContract.Groups.CONTENT_URI, true, mSpeakerChangesObserver);
}
@Override
public void onPause() {
super.onPause();
getApplicationContext().getContentResolver().unregisterContentObserver(
mSpeakerChangesObserver);
}
// method to expand all groups
private void expandAll() {
int count = listAdapter.getGroupCount();
for (int i = 0; i < count; i++) {
myList.expandGroup(i);
}
}
public LoaderManager.LoaderCallbacks<Cursor> mSpeakersLoaderCallback = new LoaderCallbacks<Cursor>() {
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
Log.d(DEBUG_TAG, "onCreateLoader for loader_id " + id);
CursorLoader cl = null;
if (id != -1) {
if (id == 7) {
cl = new CursorLoader(getApplicationContext(),
CfpContract.Classes.CONTENT_URI,
MyListAdapter.CLASSES_PROJECTION, null, null,
CfpContract.Classes.DEFAULT_SORT);
} else if (id == 8) {
cl = new CursorLoader(getApplicationContext(),
CfpContract.Teachers.CONTENT_URI,
MyListAdapter.TEACHERS_PROJECTION, null, null,
CfpContract.Teachers.DEFAULT_SORT);
}
} else {
// group cursor
cl = new CursorLoader(getApplicationContext(),
CfpContract.Groups.CONTENT_URI,
MyListAdapter.GROUPS_PROJECTION, null, null,
CfpContract.Groups.DEFAULT_SORT);
}
return cl;
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
// Swap the new cursor in.
int id = loader.getId();
Log.d("Dump Cursor MainActivity",
DatabaseUtils.dumpCursorToString(data));
Log.d(DEBUG_TAG, "onLoadFinished() for loader_id " + id);
if (id != -1) {
// child cursor
if (!data.isClosed()) {
Log.d(DEBUG_TAG, "data.getCount() " + data.getCount());
HashMap<Integer, Integer> groupMap = listAdapter
.getGroupMap();
try {
int groupPos = groupMap.get(id);
Log.d(DEBUG_TAG, "onLoadFinished() for groupPos "
+ groupPos);
listAdapter.setChildrenCursor(groupPos, data);
} catch (NullPointerException e) {
Log.w("DEBUG",
"Adapter expired, try again on the next query: "
+ e.getMessage());
}
}
} else {
listAdapter.setGroupCursor(data);
}
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
// This is called when the last Cursor provided to onLoadFinished()
// is about to be closed.
int id = loader.getId();
Log.d(DEBUG_TAG, "onLoaderReset() for loader_id " + id);
if (id != 1) {
// child cursor
try {
listAdapter.setChildrenCursor(id, null);
} catch (NullPointerException e) {
Log.w(DEBUG_TAG,
"Adapter expired, try again on the next query: "
+ e.getMessage());
}
} else {
listAdapter.setGroupCursor(null);
}
}
};
private ContentObserver mSpeakerChangesObserver = new ContentObserver(
new Handler()) {
@Override
public void onChange(boolean selfChange) {
if (getApplicationContext() != null) {
runOnUiThread(new Runnable() {
public void run() {
getSupportLoaderManager().restartLoader(-1, null,
mSpeakersLoaderCallback);
}
});
}
}
};
}
MyListAdapter.java:
Code:
package com.example.android.exlistexample;
import java.util.HashMap;
import android.content.Context;
import android.database.Cursor;
import android.provider.BaseColumns;
import android.support.v4.content.Loader;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CursorTreeAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.example.android.exlistexample.provider.CfpContract;
import com.example.android.exlistexample.provider.CfpContract.Groups;
import com.joanzapata.android.iconify.Iconify;
import com.joanzapata.android.iconify.Iconify.IconValue;
public class MyListAdapter extends CursorTreeAdapter {
public HashMap<String, View> childView = new HashMap<String, View>();
/**
* The columns we are interested in from the database
*/
protected static final String[] GROUPS_PROJECTION = new String[] {
BaseColumns._ID, CfpContract.Groups.GROUP_ID,
CfpContract.Groups.GROUP_NAME, CfpContract.Groups.GROUP_IMAGE, };
protected static final String[] CLASSES_PROJECTION = new String[] {
BaseColumns._ID, CfpContract.Classes.CLASS_ID,
CfpContract.Classes.CLASS_NAME, CfpContract.Classes.CLASS_CAT, };
protected static final String[] TEACHERS_PROJECTION = new String[] {
BaseColumns._ID, CfpContract.Teachers.TEACHER_ID,
CfpContract.Teachers.TEACHER_NAME,
CfpContract.Teachers.TEACHER_SHORT,
CfpContract.Teachers.TEACHER_OPLEIDINGEN, };
private final String DEBUG_TAG = getClass().getSimpleName().toString();
protected final HashMap<Integer, Integer> mGroupMap;
private MainActivity mActivity;
private LayoutInflater mInflater;
public MyListAdapter(Cursor cursor, Context context) {
super(cursor, context);
mActivity = (MainActivity) context;
mInflater = LayoutInflater.from(context);
mGroupMap = new HashMap<Integer, Integer>();
}
@Override
public View newGroupView(Context context, Cursor cursor,
boolean isExpanded, ViewGroup parent) {
final View view = mInflater.inflate(R.layout.list_group, parent, false);
return view;
}
@Override
public void bindGroupView(View view, Context context, Cursor cursor,
boolean isExpanded) {
TextView lblListHeader = (TextView) view
.findViewById(R.id.lblListHeader);
if (lblListHeader != null) {
lblListHeader.setText(cursor.getString(cursor
.getColumnIndex(Groups.GROUP_NAME)));
ImageView groupIcon = (ImageView) view
.findViewById(R.id.lblListHeaderIcon);
groupIcon.setImageResource(cursor.getInt(cursor
.getColumnIndex(Groups.GROUP_IMAGE)));
}
TextView IndicatorText = (TextView) view
.findViewById(R.id.lblListHeaderIndicator);
if (IndicatorText != null) {
if (isExpanded) {
Iconify.setIcon(IndicatorText, IconValue.icon_caret_up);
} else {
Iconify.setIcon(IndicatorText, IconValue.icon_caret_down);
}
}
}
@Override
public View newChildView(Context context, Cursor cursor,
boolean isLastChild, ViewGroup parent) {
final View view = mInflater.inflate(R.layout.list_item, parent, false);
return view;
}
@Override
public void bindChildView(View view, Context context, Cursor cursor,
boolean isLastChild) {
TextView txtListChild = (TextView) view.findViewById(R.id.lblListItem);
txtListChild.setText(cursor.getString(2));
}
protected Cursor getChildrenCursor(Cursor groupCursor) {
// Given the group, we return a cursor for all the children within that
// group
int groupPos = groupCursor.getPosition();
int groupId = groupCursor.getInt(groupCursor
.getColumnIndex(BaseColumns._ID));
Log.d(DEBUG_TAG, "getChildrenCursor() for groupPos " + groupPos);
Log.d(DEBUG_TAG, "getChildrenCursor() for groupId " + groupId);
mGroupMap.put(groupId, groupPos);
Loader loader = mActivity.getSupportLoaderManager().getLoader(groupId);
if (loader != null && !loader.isReset()) {
mActivity.getSupportLoaderManager().restartLoader(groupId, null,
mActivity.mSpeakersLoaderCallback);
} else {
mActivity.getSupportLoaderManager().initLoader(groupId, null,
mActivity.mSpeakersLoaderCallback);
}
return null;
}
// Access method
public HashMap<Integer, Integer> getGroupMap() {
return mGroupMap;
}
public void filterData(String query) {
// TODO Filter the data here
}
}
I have very considerably simplified and cleaned the code (so that you guys that not need to do).
As you can see, I've in total 3 cursors (1 for the groups and 2 for the children). The data is synced from a local database and put in a Content Provider. (The database is from here and the provider from here). From there I insert it into the CursorTreeAdapter. (The most of the loader functions is from here).
The only thing is now how do I implement a search? Should I do it trough Content Provider or a raw query in the database? I would like that the results of both children tables is displayed. I think because it's easy to make a fault while typing that `tokenize=porter` is a option in my case.
I've tried this in MyListAdapter.java (with FilterQueryProvider as someone suggested on Stack Overflow):
Code:
public void filterList(CharSequence constraint) {
final Cursor oldCursor = getCursor();
setFilterQueryProvider(filterQueryProvider);
getFilter().filter(constraint, new FilterListener() {
public void onFilterComplete(int count) {
// assuming your activity manages the Cursor
// (which is a recommended way)
notifyDataSetChanged();
// stopManagingCursor(oldCursor);
// final Cursor newCursor = getCursor();
// startManagingCursor(newCursor);
// // safely close the oldCursor
if (oldCursor != null && !oldCursor.isClosed()) {
oldCursor.close();
}
}
});
}
private FilterQueryProvider filterQueryProvider = new FilterQueryProvider() {
public Cursor runQuery(CharSequence constraint) {
// assuming you have your custom DBHelper instance
// ready to execute the DB request
String s = '%' + constraint.toString() + '%';
return mActivity.getContentResolver().query(CfpContract.Classes.CONTENT_URI,
MyListAdapter.CLASSES_PROJECTION,
CfpContract.Classes.CLASS_NAME + " LIKE ? OR " + CfpContract.Classes.CLASS_CAT + " LIKE ?",
new String[] { s, s },
null);
}
};
And this in MainActivity.java:
Code:
search.setOnQueryTextListener(new OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
listAdapter.filterList(query);
expandAll();
return false;
}
@Override
public boolean onQueryTextChange(String query) {
listAdapter.filterList(query);
expandAll();
return false;
}
});
search.setOnCloseListener(new OnCloseListener() {
@Override
public boolean onClose() {
listAdapter.filterList("");
expandAll();
return false;
}
});
But then I get these errors when I try to search:
Code:
12-20 13:20:19.449: E/CursorWindow(28747): Failed to read row 0, column -1 from a CursorWindow which has 96 rows, 4 columns.
12-20 13:20:19.449: D/AndroidRuntime(28747): Shutting down VM
12-20 13:20:19.449: W/dalvikvm(28747): threadid=1: thread exiting with uncaught exception (group=0x415c62a0)
12-20 13:20:19.499: E/AndroidRuntime(28747): FATAL EXCEPTION: main
12-20 13:20:19.499: E/AndroidRuntime(28747): java.lang.IllegalStateException: Couldn't read row 0, col -1 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it.
What I'm doing wrong? Or is this because I'm only return 1 query (Classes) instead of 2 (Classes and Teachers) in runQuery?
I hope that someone can point me in a good direction.

Related

Totally stumped...zoom control issue

I'm developing an application that utilizes zooming in and out (for readability) and allows for swiping left and right to change pages.
Basically the flipping back and forth part works and zoom works. However, if I do any kind of zooming and then try to change a page the program crashes.
I've only tested this on the Epic 4G and on the G2 with the same problem.
Any help that can tell me what is going on or what I need to change would be greatly appreciated. (I tried to code out on the net to fix the HTC incredible having this kind of issue but the problem is still there)
Code:
package my.package;
import java.io.IOException;
import java.io.InputStreamReader;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.AssetManager;
import android.os.Bundle;
import android.util.Log;
import android.view.GestureDetector;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.SubMenu;
import android.view.View;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.View.OnTouchListener;
import android.webkit.WebView;
public class LessonShower extends Activity {
private char[] buffer = new char[128];
private WebView webView;
private int lessonNumber, lessonPage;
private AssetManager assetManager;
private int lessonsCount;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
int lessonNumber = getIntent().getIntExtra("lessonNumber", 1);
int lessonPage = getIntent().getIntExtra("lessonPage", 1);
webView = new MyWebView(this);
assetManager = getAssets();
try {
lessonsCount = assetManager.list("").length - 3;
loadPage(lessonNumber, lessonPage);
} catch (IOException e) {
}
SimpleOnGestureListener gestureListener = new SimpleOnGestureListener(){
private static final int SWIPE_MIN_DISTANCE = 120;
private static final int SWIPE_THRESHOLD_VELOCITY = 200;
@Override
public boolean onDown(MotionEvent e) {
return true;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2,
float velocityX, float velocityY) {
Log.d("debugging", "onFling");
if(Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY && e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE){
loadNextPage();
return true;
}
else if(e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE){
loadPrevPage();
return true;
}
if(e1.getY() - e2.getY() > SWIPE_MIN_DISTANCE){
webView.pageDown(false);
}
else if(e2.getY() - e1.getY() > SWIPE_MIN_DISTANCE){
webView.pageUp(false);
}
return super.onFling(e1, e2, velocityX, velocityY);
}
};
final GestureDetector gDetector = new GestureDetector(webView.getContext(), gestureListener);
webView.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View arg0, MotionEvent arg1) {
return gDetector.onTouchEvent(arg1);
}
});
webView.getSettings().setBuiltInZoomControls(true);
setContentView(webView);
}
public void loadNextPage(){
int nextPage = lessonPage + 1;
try{
InputStreamReader is = new InputStreamReader(assetManager.open("lesson" + lessonNumber + "/" + nextPage + ".html"));
readPage(is);
lessonPage++;
}
catch(IOException ex){
final CharSequence[] items = {"Home", "Next lesson"};
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Choose an action");
builder.setItems(items, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
if(item == 0){
finish();
}
else{
if(lessonNumber < lessonsCount){
lessonNumber++;
lessonPage = 1;
loadPage(lessonNumber, lessonPage);
}
}
}
});
AlertDialog alert = builder.create();
alert.show();
}
}
public void loadPrevPage(){
if(lessonPage > 1){
try{
InputStreamReader is = new InputStreamReader(assetManager.open("lesson" + lessonNumber + "/" + --lessonPage + ".html"));
readPage(is);
}
catch(IOException ex){}
}
}
private void readPage(InputStreamReader is){
StringBuilder webPage = new StringBuilder();
int len = 0;
try {
while((len = is.read(buffer)) > 0){
webPage.append(buffer, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
}
webView.loadData(webPage.toString(), "", "");
}
public void loadPage(int lessonNumber, int lessonPage){
if(lessonNumber > lessonsCount){
return;
}
this.lessonNumber = lessonNumber;
this.lessonPage = lessonPage;
setTitle("Lesson" + lessonNumber);
InputStreamReader is = null;
try {
is = new InputStreamReader(assetManager.open("lesson" + lessonNumber + "/" + lessonPage + ".html"));
} catch (IOException e) {
}
readPage(is);
}
private static final int homeMenuItem = 1;
private static final int exitMenuItem = 2;
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
menu.add(Menu.NONE, homeMenuItem, Menu.NONE, "Home");
SubMenu pagesMenu = menu.addSubMenu("Pages");
try {
int lessonPages = assetManager.list("lesson" + lessonNumber).length;
for(int i = 1; i <= lessonPages; i++)
//"+ 1000" is used to escape collision with other menu items
pagesMenu.add(Menu.NONE, i + 1000, Menu.NONE, "Page" + i);
} catch (IOException e) {}
finally{
menu.add(Menu.NONE, exitMenuItem, Menu.NONE, "Hide");
}
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
super.onOptionsItemSelected(item);
switch(item.getItemId()){
case homeMenuItem:
finish();
break;
case exitMenuItem:
moveTaskToBack(true);
break;
default:
//Page was selected
if(item.getItemId() > 1000){
lessonPage = item.getItemId() - 1000;
loadPage(lessonNumber, lessonPage);
}
}
return true;
}
}
class MyWebView extends WebView{
private LessonShower lp = null;
public MyWebView(Context context) {
super(context);
lp = (LessonShower) context;
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event){
if(keyCode == KeyEvent.KEYCODE_DPAD_LEFT){
lp.loadPrevPage();
}
else if(keyCode == KeyEvent.KEYCODE_DPAD_RIGHT){
lp.loadNextPage();
}
return false;
}
}
No ideas? Anyone?
Sent from my SPH-D700 using XDA App

Pass Connection Between Intents

I am building an android application to do various queries on my MySQL database. Once a successful login has returned on the main activity, I create a new Intent that holds search and query options. Here's the issue I am having. I keep getting a null pointer exception on stmt = con.createStatement(); Below is my logcat:
Code:
08-20 16:12:07.359 654-810/com.android.exchange D/ExchangeService: !!! deviceId unknown; stopping self and retrying
08-20 16:12:08.469 36-653/? E/SurfaceFlinger: ro.sf.lcd_density must be defined as a build property
08-20 16:12:11.559 1926-1949/com.example.testapplication W/System.err: java.lang.NullPointerException
08-20 16:12:11.559 1926-1949/com.example.testapplication W/System.err: at com.example.testapplication.Networking.Search(Networking.java:44)
08-20 16:12:11.559 1926-1949/com.example.testapplication W/System.err: at com.example.testapplication.ControlActivity$1.run(ControlActivity.java:53)
08-20 16:12:11.559 1926-1949/com.example.testapplication W/System.err: at java.lang.Thread.run(Thread.java:856)
08-20 16:12:12.369 654-654/com.android.exchange D/ExchangeService: !!! EAS ExchangeService, onStartCommand, startingUp = false, running = false
08-20 16:12:12.369 278-498/system_process W/ActivityManager: Unable to start service Intent { act=com.android.email.ACCOUNT_INTENT } U=0: not found
08-20 16:12:12.369 654-815/com.android.exchange D/ExchangeService: !!! Email application not found; stopping self
08-20 16:12:12.379 278-278/system_process W/ActivityManager: Unable to start service Intent { act=com.android.email.ACCOUNT_INTENT } U=0: not found
I'm curious whether it is better practice to close the connection and reopen it in the new intent? Or pass the connection between intents somehow?
Any input would be greatly appreciated!
wait...
Here are snippets of my code to help debug.
Code:
[user=439709]@override[/user]
public void onClick(View view) {
if(view.getId() == R.id.LoginButton) {
Toast.makeText(getApplicationContext(), "Attempting Connection", Toast.LENGTH_SHORT).show();
//Spawn new thread
new Thread(new Runnable() {
public void run() {
if(net.execLogin(mUserInput.getText().toString(), mPassInput.getText().toString())) {
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(getApplicationContext(), "Connected to Database", Toast.LENGTH_LONG).show();
}
});
//start new activity
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
[user=439709]@override[/user]
public void run() {
Intent intent = new Intent(LoginActivity.this, ControlActivity.class);
startActivity(intent);
}
});
}
else {
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(getApplicationContext(), "Connection Failed :(", Toast.LENGTH_LONG).show();
}
});
}
}
}).start();
}
}
And here is the new activity started by the above code:
Code:
package com.example.testapplication;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;
import java.util.ArrayList;
public class ControlActivity extends Activity implements View.OnClickListener {
private ArrayList<Hardware> list = new ArrayList<Hardware>();
EditText mEditText;
ListView mListView;
[user=439709]@override[/user]
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_control);
setupPage();
}
public void setupPage() {
Button search = (Button)findViewById(R.id.search);
search.setOnClickListener(this);
mEditText = (EditText)findViewById(R.id.editText);
mListView = (ListView)findViewById(R.id.listView);
}
[user=439709]@override[/user]
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.control, menu);
return true;
}
public void onClick(View view) {
if(view.getId() == R.id.search) {
new Thread(new Runnable() {
public void run() {
list = new Networking().Search("Type", mEditText.getText().toString());
}
}).start();
ArrayAdapter<Hardware> adapter = new ArrayAdapter<Hardware>(this, android.R.layout.simple_list_item_1, list);
adapter.notifyDataSetChanged();
mListView.setAdapter(adapter);
if(list == null) {
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(getApplicationContext(), "0 Results Yielded :(", Toast.LENGTH_SHORT).show();
}
});
}
}
}
}
And here is the code I use to connect and query the database
Code:
import java.sql.*;
import java.util.*;
public class Networking implements DbQuery {
private static final String DRIVER = "org.mariadb.jdbc.Driver";
private static final String URL = "jdbc:mysql://146.187.16.32/Peirce";
ArrayList<Hardware> ara = new ArrayList<Hardware>();
Database db = new Database();
Hardware h1;
Connection con = null;
Statement stmt = null;
public boolean execLogin(String uName, String pWord) {
try {
Class.forName(DRIVER);
con = DriverManager.getConnection(URL, uName, pWord);
if(!con.isClosed()){
return true;
}
return false;
}catch(SQLException e) {
e.printStackTrace();
}catch(ClassNotFoundException e) {
e.printStackTrace();
}
return false;
}
public ArrayList<Hardware> Search(String arg, String target) {
try {
stmt = con.createStatement(); //throws null pointer exception
ResultSet rs = stmt.executeQuery("Select * from " + db.getTable() + " where " + arg + "='" + target + "';");
while(rs.next()) {
ara.add(new Hardware(rs.getString("Type"), rs.getString("Make"), rs.getString("Model"), rs.getString("Serial"), rs.getString("Comments")));
}
return ara;
}catch(SQLException e) {
e.printStackTrace();
}catch(NullPointerException e) {
e.printStackTrace();
}
return ara;
}
nevermind
i have figured it out.

url loading handling in webview

Basic question, what did i do? Hahaha. What did i do to make url load inside webview?
At first i overridden shouldOverrideUrlLoading to control where the link loads, then i one time i removed it but url still loads inside webview. And now i need to once again override url loading because i need a link to be opened on the default browser, but i don't know how. I even tried what others suggested to force url loading on the default browser, but it doesn't work. Please help me. Here's my code:
Code:
package com.sample;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Bundle;
import android.os.StrictMode;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.graphics.Bitmap;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ProgressBar;
import android.widget.Toast;
public class MainActivity extends Activity
{
private WebView wv;
private ProgressBar progress;
private static String mycaturl="*url 1*";
private static String helpurl="*url 2*";
private static String fbackurl="*url 3*";
[user=1299008]@supp[/user]ressLint("NewApi")
[user=439709]@override[/user]
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitNetwork().build();
StrictMode.setThreadPolicy(policy);
if (reachable(this))
{
Toast.makeText(this, "Reachable", Toast.LENGTH_SHORT).show();
buildwv( savedInstanceState, WebSettings.LOAD_DEFAULT, mycaturl );
}
else
{
Toast.makeText(this, "Unreachable", Toast.LENGTH_SHORT).show();
eolc( savedInstanceState );
}
}
[user=1299008]@supp[/user]ressLint({ "SetJavaScriptEnabled" })
public void buildwv(Bundle sis, int load, String url)
{
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
setContentView(R.layout.activity_main);
//assigning objects to variables
wv=(WebView) findViewById(R.id.wv);
wv.setWebViewClient( new wvc() );
progress=(ProgressBar) findViewById(R.id.progress);
//websettings
WebSettings ws = wv.getSettings();
ws.setAppCacheMaxSize( 100 * 1024 * 1024 ); // 100MB
ws.setAppCachePath( this.getCacheDir().getAbsolutePath() );
ws.setAllowFileAccess( true );
ws.setAppCacheEnabled( true );
ws.setJavaScriptEnabled( true );
ws.setCacheMode(load);
//if instance is saved, to catch orientation change
if(sis==null)
{ wv.loadUrl(url); }
}
public void eolc(final Bundle sis)
{
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
AlertDialog.Builder alertDialog = new AlertDialog.Builder( MainActivity.this );
alertDialog.setTitle("Unreachable Host");
alertDialog.setMessage("Host is unreachable. Load from cache or exit.");
alertDialog.setIcon(R.drawable.tick);
//alertDialog.setCanceledOnTouchOutside(false);
alertDialog.setCancelable(false);
alertDialog.setPositiveButton( "Load from Cache", new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog,int which)
{
// Write your code here to execute after dialog
Toast.makeText(getApplicationContext(), "You chose to load cache.", Toast.LENGTH_SHORT).show();
buildwv( sis, WebSettings.LOAD_CACHE_ELSE_NETWORK, mycaturl );
}
});
alertDialog.setNeutralButton( "Help", new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int which)
{
Toast.makeText(getApplicationContext(), "You chose Help. EOLC", Toast.LENGTH_SHORT).show();
buildwv( sis, WebSettings.LOAD_CACHE_ELSE_NETWORK, helpurl );
}
});
alertDialog.setNegativeButton( "Exit", new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int which)
{
// Write your code here to execute after dialog
Toast.makeText(getApplicationContext(), "You chose to exit.", Toast.LENGTH_SHORT).show();
finish();
}
});
alertDialog.create();
alertDialog.show();
}
public void roe()
{
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
AlertDialog.Builder alertDialog = new AlertDialog.Builder( MainActivity.this );
alertDialog.setTitle("Connection Lost");
alertDialog.setMessage("Connection to host was lost. Restart and load cache or exit.");
alertDialog.setIcon(R.drawable.tick);
alertDialog.setCancelable(false);
alertDialog.setPositiveButton( "Restart", new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog,int which)
{
Toast.makeText(getApplicationContext(), "You chose to restart and load cache.", Toast.LENGTH_SHORT).show();
Intent i = getBaseContext().getPackageManager()
.getLaunchIntentForPackage( getBaseContext().getPackageName() );
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK );
startActivity(i);
}
});
alertDialog.setNeutralButton( "Help", new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int which)
{
Toast.makeText(getApplicationContext(), "You chose Help. ROE", Toast.LENGTH_SHORT).show();
wv.stopLoading();
wv.loadUrl( helpurl );
}
});
alertDialog.setNegativeButton( "Exit", new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int which)
{
Toast.makeText(getApplicationContext(), "You chose to exit.", Toast.LENGTH_SHORT).show();
finish();
}
});
alertDialog.create();
alertDialog.show();
}
private class wvc extends WebViewClient
{
public void onPageStarted(WebView view, String url, Bitmap favicon)
{
progress.setVisibility(View.VISIBLE);
if (url.contains(mycaturl))
{
WebSettings ws = wv.getSettings();
if ( !reachable(getApplicationContext()) )
{
if ( ws.getCacheMode() == WebSettings.LOAD_DEFAULT )
{
roe();
}
else if ( ws.getCacheMode() == WebSettings.LOAD_CACHE_ELSE_NETWORK )
{
Toast.makeText(getApplicationContext(), "loading cache coz not reachable", Toast.LENGTH_SHORT).show();
}
}
else
{
if ( ws.getCacheMode() == WebSettings.LOAD_CACHE_ELSE_NETWORK )
{
Toast.makeText(getApplicationContext(), "Connection to server established.", Toast.LENGTH_SHORT).show();
}
}
}
}
[user=439709]@override[/user]
public void onPageFinished(WebView view, String url)
{
super.onPageFinished(view, url);
Toast.makeText(getApplicationContext(), "PAGE DONE LOADING!!", Toast.LENGTH_SHORT).show();
//circular progress bar close
progress.setVisibility(View.GONE);
}
[user=439709]@override[/user]
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl)
{
super.onReceivedError(view, errorCode, description, failingUrl);
wv.stopLoading();
WebSettings ws = wv.getSettings();
if ( ws.getCacheMode() == WebSettings.LOAD_DEFAULT )
{
wv.loadUrl(helpurl);
Toast.makeText(getApplicationContext(), "Page unavailable", Toast.LENGTH_SHORT).show();
}
else
{
wv.loadUrl(helpurl);
Toast.makeText(getApplicationContext(), "Page not cached", Toast.LENGTH_SHORT).show();
}
roe();
}
}
//checking connectivity by checking if site is reachable
public static boolean reachable(Context context)
{
final ConnectivityManager connMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
final NetworkInfo netInfo = connMgr.getActiveNetworkInfo();
if (netInfo != null && netInfo.isConnected())
{
try
{
URL url = new URL(mycaturl);
HttpURLConnection urlc = (HttpURLConnection) url.openConnection();
urlc.setConnectTimeout(5000); // five seconds timeout in milliseconds
urlc.connect();
if (urlc.getResponseCode() == 200) // good response
{ return true; } else { return false; }
}
catch (IOException e)
{ return false; }
}
else
{ return false; }
}
[user=439709]@override[/user]
public boolean onCreateOptionsMenu(Menu menu)
{
super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public void onBackPressed ()
{
if (wv.isFocused() && wv.canGoBack())
{ wv.goBack(); } else { finish(); }
}
[user=439709]@override[/user]
public boolean onOptionsItemSelected(MenuItem item)
{
switch (item.getItemId())
{
case R.id.item1:
wv.loadUrl( helpurl );
break;
case R.id.item2:
wv.loadUrl( fbackurl );
break;
case R.id.item3:
String currurl=wv.getUrl();
wv.loadUrl(currurl);
break;
case R.id.item4:
Intent i = getBaseContext().getPackageManager()
.getLaunchIntentForPackage( getBaseContext().getPackageName() );
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
break;
case R.id.item5:
finish();
break;
default:
break;
}
return true;
}
[user=439709]@override[/user]
protected void onSaveInstanceState(Bundle outState )
{
super.onSaveInstanceState(outState);
wv.saveState(outState);
}
[user=439709]@override[/user]
protected void onRestoreInstanceState(Bundle savedInstanceState)
{
super.onSaveInstanceState(savedInstanceState);
wv.restoreState(savedInstanceState);
}
}
Should i include manifest? Thanks in advance.
That's a messed Op . If your code is short. use code tags. If its big, use paste bin to make it easy for people to read the question and answer it!
vijai2011 said:
That's a messed Op . If your code is short. use code tags. If its big, use paste bin to make it easy for people to read the question and answer it!
Click to expand...
Click to collapse
Sorry, I'm still a newbie. Can you please teach me the proper way of coding android?
klutchmeister said:
Sorry, I'm still a newbie. Can you please teach me the proper way of coding android?
Click to expand...
Click to collapse
He just said that you should wrap your code into
Code:
tags or upload it elsewhere because nobody will read it as it is right now. Can you read that code from your browser? If you put it into [CODE] tags, it will look like this: [URL]http://forum.xda-developers.com/showthread.php?p=44976604#post44976604[/URL]
Then people will be able to read it. ;)
nikwen said:
He just said that you should wrap your code into
Code:
tags or upload it elsewhere because nobody will read it as it is right now. Can you read that code from your browser? If you put it into [CODE] tags, it will look like this: [URL]http://forum.xda-developers.com/showthread.php?p=44976604#post44976604[/URL]
Then people will be able to read it. ;)[/QUOTE]
Oh. sorry. Haha. There, thanks. :)
Click to expand...
Click to collapse

[Q]Put view over status bar

I want to put a View over the status bar, the code work right, but I get a RunTime Error.
Code:
//Declared in the Activity
WindowManager wm;
LinearLayout ll;
WindowManager.LayoutParams ll_lp;
//Just a sample layout parameters.
ll_lp = new WindowManager.LayoutParams();
ll_lp.format = PixelFormat.TRANSLUCENT;
ll_lp.height = WindowManager.LayoutParams.FILL_PARENT;
ll_lp.width = WindowManager.LayoutParams.FILL_PARENT;
ll_lp.gravity = Gravity.CLIP_HORIZONTAL | Gravity.TOP;
//This one is necessary.
ll_lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
//Play around with these two.
ll_lp.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
ll_lp.flags = ll_lp.flags | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
//This is our main layout.
ll = new LinearLayout(LockScreenAppActivity.this);
ll.setBackgroundColor(android.graphics.Color.argb(0, 0, 0, 0));
ll.setHapticFeedbackEnabled(true);
try {
//And finally we add what we created to the screen.
wm.addView(ll, ll_lp);
} catch (Exception e) {
//I GET THE ERROR HERE
Log.e("Error", "Fail");
e.printStackTrace();
e.getMessage();
}
Code:
LOG:
11-29 23:38:38.109: W/System.err(6462): java.lang.NullPointerException
11-29 23:38:38.117: W/System.err(6462): at com.advanced.locker.LockScreenAppActivity.onCreate(LockScreenAppActivity.java:77)
11-29 23:38:38.117: W/System.err(6462): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
11-29 23:38:38.117: W/System.err(6462): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1615)
11-29 23:38:38.117: W/System.err(6462): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1667)
11-29 23:38:38.117: W/System.err(6462): at android.app.ActivityThread.access$1500(ActivityThread.java:117)
11-29 23:38:38.117: W/System.err(6462): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:935)
11-29 23:38:38.125: W/System.err(6462): at android.os.Handler.dispatchMessage(Handler.java:99)
11-29 23:38:38.125: W/System.err(6462): at android.os.Looper.loop(Looper.java:130)
11-29 23:38:38.125: W/System.err(6462): at android.app.ActivityThread.main(ActivityThread.java:3687)
11-29 23:38:38.125: W/System.err(6462): at java.lang.reflect.Method.invokeNative(Native Method)
11-29 23:38:38.125: W/System.err(6462): at java.lang.reflect.Method.invoke(Method.java:507)
11-29 23:38:38.125: W/System.err(6462): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
11-29 23:38:38.125: W/System.err(6462): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:625)
11-29 23:38:38.125: W/System.err(6462): at dalvik.system.NativeStart.main(Native Method)
11-29 23:45:55.953: E/Error(6884): Fail
11-29 23:55:39.070: W/IInputConnectionWrapper(6884): showStatusIcon on inactive InputConnection
11-29 23:55:53.226: E/Error(7053): Fail
Can anybody help me?
Lot's of thank's!
Don't know whether you idea is possible, but please DO NOT code an empty catch part. Something like e.printStackTrace() and e.getMessage() AT LEAST.
Regards
EmptinessFiller said:
Don't know whether you idea is possible, but please DO NOT code an empty catch part. Something like e.printStackTrace() and e.getMessage() AT LEAST.
Regards
Click to expand...
Click to collapse
Is Correct NOW?
Thank's
It might be correct, but senseless, because you never see e.getMessage(). So u could use Log.e(TAG, e.getMessage()).
But by the way, it'd be great if you'd post your log here and before read it.
Regards
EmptinessFiller said:
It might be correct, but senseless, because you never see e.getMessage(). So u could use Log.e(TAG, e.getMessage()).
But by the way, it'd be great if you'd post your log here and before read it.
Regards
Click to expand...
Click to collapse
Now, i think is fine
Come on please, it's easy, but for me no...
Enviado desde mi GT-S5570I usando Tapatalk 2
You define a variable of type WindowManager but you never assign any object to it.
Add this before the try:
Code:
wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
nikwen said:
You define a variable of type WindowManager but you never assign any object to it.
Add this before the try:
Code:
wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
Click to expand...
Click to collapse
Lot's of Thank's friend!
Do you think that I put a view over status bar with it??
Enviado desde mi GT-S5570I usando Tapatalk 2
nikwen said:
You define a variable of type WindowManager but you never assign any object to it.
Add this before the try:
Code:
wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
Click to expand...
Click to collapse
Your code works fine, but i can get what i want...
I need something like this:
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
(Red square)
But my view is under the status bar.
Can u help me?
Thank's in advance!
Enviado desde mi GT-S5570I usando Tapatalk 2
DannyGM16 said:
Your code works fine, but i can get what i want...
I need something like this:
(Red square)
But my view is under the status bar.
Can u help me?
Thank's in advance!
Enviado desde mi GT-S5570I usando Tapatalk 2
Click to expand...
Click to collapse
Maybe you can find some hints in the code of the RoundR app which does actually do what you want to achieve: https://github.com/MohammadAdib/Roundr
nikwen said:
Maybe you can find some hints in the code of the RoundR app which does actually do what you want to achieve: https://github.com/MohammadAdib/Roundr
Click to expand...
Click to collapse
I don't find the code that I need, Help me please.
This is the code:
MainActivity.java:
Code:
package mohammad.adib.roundr;
/**
* Copyright 2013 Mohammad Adib
*
* 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.
*/
import wei.mark.standout.StandOutWindow;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
public class MainActivity extends Activity {
/**
* Main Activity that launches the 4 floating windows (corners)
*
* @author Mohammad Adib <[email protected]>
*
* Contributors: Mark Wei
*
*/
ProgressDialog progress;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
if (!BootReceiver.boot_up || Corner.running) {
Intent i = new Intent(this, SettingsActivity.class);
startActivity(i);
}
if (prefs.getBoolean("enable", true)) {
StandOutWindow.show(this, Corner.class, 0);
StandOutWindow.show(this, Corner.class, 1);
StandOutWindow.show(this, Corner.class, 2);
StandOutWindow.show(this, Corner.class, 3);
}
finish();
}
}
Corner.java:
Code:
package mohammad.adib.roundr;
/**
* Copyright 2013 Mohammad Adib
*
* 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.
*/
import wei.mark.standout.StandOutWindow;
import wei.mark.standout.constants.StandOutFlags;
import wei.mark.standout.ui.Window;
import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.RemoteViews;
public class Corner extends StandOutWindow {
/**
* The individual floating window that sits at one of the corners of the
* screen. Window ID corresponds to which corner this goes to.
*
* @author Mohammad Adib <[email protected]>
*
* Contributors: Mark Wei, Jan Metten
*
*/
public static final String ACTION_SETTINGS = "SETTINGS";
public static final String BCAST_CONFIGCHANGED = "android.intent.action.CONFIGURATION_CHANGED";
public static final int UPDATE_CODE = 2;
public static final int NOTIFICATION_CODE = 3;
public static final int wildcard = 0;
private SharedPreferences prefs;
public static boolean running = false;
@Override
public String getAppName() {
return "RoundR";
}
@Override
public int getAppIcon() {
return R.drawable.notif_icon;
}
@Override
public void createAndAttachView(int corner, FrameLayout frame) {
// Set the image based on window corner
LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
ImageView v = (ImageView) inflater.inflate(R.layout.corner, frame, true).findViewById(R.id.iv);
// Top left by default
v.setImageDrawable(getResources().getDrawable(R.drawable.topleft));
switch (corner) {
case 1:
v.setImageDrawable(getResources().getDrawable(R.drawable.topright));
break;
case 2:
v.setImageDrawable(getResources().getDrawable(R.drawable.bottomleft));
break;
case 3:
v.setImageDrawable(getResources().getDrawable(R.drawable.bottomright));
break;
}
}
private int pxFromDp(double dp) {
return (int) (dp * getResources().getDisplayMetrics().density);
}
/**
* Corners: 0 = top left; 1 = top right; 2 = bottom left; 3 = bottom right;
*/
@Override
public StandOutLayoutParams getParams(int corner, Window window) {
prefs = PreferenceManager.getDefaultSharedPreferences(this);
// Check if this corner is enabled
if (prefs.getBoolean("corner" + corner, true)) {
int radius = pxFromDp(prefs.getInt("radius", 20));
// Thanks to Jan Metten for rewriting this based on gravity
switch (corner) {
case 0:
return new StandOutLayoutParams(corner, radius, radius, Gravity.TOP | Gravity.LEFT);
case 1:
return new StandOutLayoutParams(corner, radius, radius, Gravity.TOP | Gravity.RIGHT);
case 2:
return new StandOutLayoutParams(corner, radius, radius, Gravity.BOTTOM | Gravity.LEFT);
case 3:
return new StandOutLayoutParams(corner, radius, radius, Gravity.BOTTOM | Gravity.RIGHT);
}
}
// Outside of screen
return new StandOutLayoutParams(corner, 1, 1, -1, -1, 1, 1);
}
@Override
public int getFlags(int corner) {
return super.getFlags(corner) | StandOutFlags.FLAG_WINDOW_FOCUSABLE_DISABLE | StandOutFlags.FLAG_WINDOW_EDGE_LIMITS_ENABLE;
}
@Override
public String getPersistentNotificationMessage(int corner) {
return "Tap to configure";
}
@Override
public Intent getPersistentNotificationIntent(int corner) {
return new Intent(this, Corner.class).putExtra("id", corner).setAction(ACTION_SETTINGS);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null) {
String action = intent.getAction();
int corner = intent.getIntExtra("id", DEFAULT_ID);
if (corner == ONGOING_NOTIFICATION_ID) {
throw new RuntimeException("ID cannot equals StandOutWindow.ONGOING_NOTIFICATION_ID");
}
if (ACTION_SHOW.equals(action) || ACTION_RESTORE.equals(action)) {
show(corner);
} else if (ACTION_SETTINGS.equals(action)) {
try {
Intent intentS = new Intent(this, SettingsActivity.class);
intentS.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intentS);
} catch (Exception e) {
// Addressing this issue: http://i.imgur.com/Op9kfy8.png
}
} else if (ACTION_HIDE.equals(action)) {
hide(corner);
} else if (ACTION_CLOSE.equals(action)) {
close(corner);
} else if (ACTION_CLOSE_ALL.equals(action)) {
closeAll();
} else if (ACTION_SEND_DATA.equals(action)) {
if (isExistingId(corner) || corner == DISREGARD_ID) {
Bundle data = intent.getBundleExtra("wei.mark.standout.data");
int requestCode = intent.getIntExtra("requestCode", 0);
@SuppressWarnings("unchecked")
Class<? extends StandOutWindow> fromCls = (Class<? extends StandOutWindow>) intent.getSerializableExtra("wei.mark.standout.fromCls");
int fromId = intent.getIntExtra("fromId", DEFAULT_ID);
onReceiveData(corner, requestCode, data, fromCls, fromId);
}
}
}
return START_NOT_STICKY;
}
@Override
public boolean onClose(final int corner, final Window window) {
running = false;
return false;
}
@Override
public String getPersistentNotificationTitle(int corner) {
return "Rounded Corners";
}
@SuppressLint({ "InlinedApi", "NewApi" })
@SuppressWarnings("deprecation")
@Override
public Notification getPersistentNotification(int id) {
int icon = getAppIcon();
long when = System.currentTimeMillis();
Context c = getApplicationContext();
String contentTitle = getPersistentNotificationTitle(id);
String contentText = getPersistentNotificationMessage(id);
Intent notificationIntent = getPersistentNotificationIntent(id);
PendingIntent contentIntent = PendingIntent.getService(this, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
// 4.1+ Low priority notification
final int apiLevel = Build.VERSION.SDK_INT;
if (apiLevel >= 16) {
Notification.Builder mBuilder = new Notification.Builder(this).setContent(new RemoteViews(getPackageName(), R.layout.notification)).setSmallIcon(getAppIcon()).setContentTitle(contentTitle).setContentText(contentText).setPriority(Notification.PRIORITY_MIN).setContentIntent(contentIntent);
return mBuilder.build();
}
String tickerText = String.format("%s: %s", contentTitle, contentText);
Notification notification = new Notification(icon, tickerText, when);
notification.setLatestEventInfo(c, contentTitle, contentText, contentIntent);
return notification;
}
@Override
public boolean onShow(final int corner, final Window window) {
running = true;
return false;
}
@Override
public void onReceiveData(int corner, int requestCode, Bundle data, Class<? extends StandOutWindow> fromCls, int fromId) {
Window window = getWindow(corner);
if (requestCode == UPDATE_CODE) {
// Update the corners when device is rotated
updateViewLayout(3, getParams(3, window));
updateViewLayout(2, getParams(2, window));
updateViewLayout(1, getParams(1, window));
updateViewLayout(0, getParams(0, window));
} else if (requestCode == NOTIFICATION_CODE) {
if (!prefs.getBoolean("notification", true)) {
// Hide Notification Icon (for <= Gingerbread devices only)
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = getPersistentNotification(corner);
notification.icon = wei.mark.standout.R.drawable.nothing;
mNotificationManager.notify(getClass().hashCode() + ONGOING_NOTIFICATION_ID, notification);
Log.d("Hello World", "");
} else {
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = getPersistentNotification(corner);
mNotificationManager.notify(getClass().hashCode() + ONGOING_NOTIFICATION_ID, notification);
}
}
}
}
SeekBarPreference:
Code:
package mohammad.adib.roundr;
import wei.mark.standout.StandOutWindow;
import android.content.Context;
import android.content.res.TypedArray;
import android.os.Bundle;
import android.preference.Preference;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
public class SeekBarPreference extends Preference implements OnSeekBarChangeListener {
private final String TAG = getClass().getName();
private static final String ANDROIDNS = "http://schemas.android.com/apk/res/android";
private static final String ROUNDRNS = "roundrprefs";
private static final int DEFAULT_VALUE = 50;
private int mMaxValue = 100;
private int mMinValue = 0;
private int mInterval = 1;
private int mCurrentValue;
private String mUnitsLeft = "";
private String mUnitsRight = "";
private SeekBar mSeekBar;
private Context context;
private TextView mStatusText;
public SeekBarPreference(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
initPreference(context, attrs);
}
public SeekBarPreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initPreference(context, attrs);
}
private void initPreference(Context context, AttributeSet attrs) {
setValuesFromXml(attrs);
mSeekBar = new SeekBar(context, attrs);
mSeekBar.setMax(mMaxValue - mMinValue);
mSeekBar.setOnSeekBarChangeListener(this);
}
private void setValuesFromXml(AttributeSet attrs) {
mMaxValue = attrs.getAttributeIntValue(ANDROIDNS, "max", 100);
mMinValue = attrs.getAttributeIntValue(ROUNDRNS, "min", 0);
mUnitsLeft = getAttributeStringValue(attrs, ROUNDRNS, "unitsLeft", "");
String units = getAttributeStringValue(attrs, ROUNDRNS, "units", "");
mUnitsRight = getAttributeStringValue(attrs, ROUNDRNS, "unitsRight", units);
try {
String newInterval = attrs.getAttributeValue(ROUNDRNS, "interval");
if (newInterval != null)
mInterval = Integer.parseInt(newInterval);
} catch (Exception e) {
Log.e(TAG, "Invalid interval value", e);
}
}
private String getAttributeStringValue(AttributeSet attrs, String namespace, String name, String defaultValue) {
String value = attrs.getAttributeValue(namespace, name);
if (value == null)
value = defaultValue;
return value;
}
@Override
protected View onCreateView(ViewGroup parent) {
RelativeLayout layout = null;
try {
LayoutInflater mInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
layout = (RelativeLayout) mInflater.inflate(R.layout.seek_bar_preference, parent, false);
} catch (Exception e) {
Log.e(TAG, "Error creating seek bar preference", e);
}
return layout;
}
@Override
public void onBindView(View view) {
super.onBindView(view);
try {
// move our seekbar to the new view we've been given
ViewParent oldContainer = mSeekBar.getParent();
ViewGroup newContainer = (ViewGroup) view.findViewById(R.id.seekBarPrefBarContainer);
if (oldContainer != newContainer) {
// remove the seekbar from the old view
if (oldContainer != null) {
((ViewGroup) oldContainer).removeView(mSeekBar);
}
// remove the existing seekbar (there may not be one) and add
// ours
newContainer.removeAllViews();
newContainer.addView(mSeekBar, ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
}
} catch (Exception ex) {
Log.e(TAG, "Error binding view: " + ex.toString());
}
updateView(view);
}
/**
* Update a SeekBarPreference view with our current state
*
* @param view
*/
protected void updateView(View view) {
try {
RelativeLayout layout = (RelativeLayout) view;
mStatusText = (TextView) layout.findViewById(R.id.seekBarPrefValue);
mStatusText.setText(String.valueOf(pxFromDp(mCurrentValue)));
mStatusText.setMinimumWidth(30);
mSeekBar.setProgress(mCurrentValue - mMinValue);
} catch (Exception e) {
Log.e(TAG, "Error updating seek bar preference", e);
}
}
private int pxFromDp(double dp) {
return (int) (dp * context.getResources().getDisplayMetrics().density);
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
int newValue = progress + mMinValue;
if (newValue > mMaxValue)
newValue = mMaxValue;
else if (newValue < mMinValue)
newValue = mMinValue;
else if (mInterval != 1 && newValue % mInterval != 0)
newValue = Math.round(((float) newValue) / mInterval) * mInterval;
// change rejected, revert to the previous value
if (!callChangeListener(newValue)) {
seekBar.setProgress(mCurrentValue - mMinValue);
return;
}
// change accepted, store it
mCurrentValue = newValue;
mStatusText.setText(String.valueOf(pxFromDp(newValue)));
persistInt(newValue);
// Refresh the corners to apply the new radius
StandOutWindow.sendData(context, Corner.class, Corner.wildcard, Corner.UPDATE_CODE, new Bundle(), Corner.class, StandOutWindow.DISREGARD_ID);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
notifyChanged();
}
@Override
protected Object onGetDefaultValue(TypedArray ta, int index) {
int defaultValue = ta.getInt(index, DEFAULT_VALUE);
return defaultValue;
}
@Override
protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
if (restoreValue) {
mCurrentValue = getPersistedInt(mCurrentValue);
} else {
int temp = 0;
try {
temp = (Integer) defaultValue;
} catch (Exception ex) {
Log.e(TAG, "Invalid default value: " + defaultValue.toString());
}
persistInt(temp);
mCurrentValue = temp;
}
}
}
SettingsActivity.java:
Code:
package mohammad.adib.roundr;
import wei.mark.standout.StandOutWindow;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.preference.Preference;
import android.preference.PreferenceManager;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceActivity;
import android.util.Log;
import android.view.WindowManager.LayoutParams;
public class SettingsActivity extends PreferenceActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
/**
* Handle Preference Changes
*/
// Enable/Disable
((Preference) findPreference("enable")).setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
boolean isChecked = (Boolean) newValue;
if (isChecked) {
StandOutWindow.show(SettingsActivity.this, Corner.class, 0);
StandOutWindow.show(SettingsActivity.this, Corner.class, 1);
StandOutWindow.show(SettingsActivity.this, Corner.class, 2);
StandOutWindow.show(SettingsActivity.this, Corner.class, 3);
} else {
StandOutWindow.closeAll(SettingsActivity.this, Corner.class);
}
return true;
}
});
// Notification
final int apiLevel = Build.VERSION.SDK_INT;
if (apiLevel >= 16) {
((Preference) findPreference("notification")).setOnPreferenceClickListener(new OnPreferenceClickListener() {
public boolean onPreferenceClick(Preference preference) {
new AlertDialog.Builder(SettingsActivity.this).setTitle("Notification").setMessage("The notification prevents Android from killing RoundR in low memory situations.\n\nOn Android 4.1+ devices, it can be disabled via the App Info.").setPositiveButton("Continue", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
showInstalledAppDetails("mohammad.adib.roundr");
}
}).show();
return true;
}
});
}else{
((Preference) findPreference("notification")).setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
StandOutWindow.sendData(SettingsActivity.this, Corner.class, Corner.wildcard, Corner.NOTIFICATION_CODE, new Bundle(), Corner.class, StandOutWindow.DISREGARD_ID);
return true;
}
});
}
// Enable specific corners
for (int i = 0; i < 4; i++) {
((Preference) findPreference("corner" + i)).setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
refresh();
return true;
}
});
}
/**
* Overlap Settings TODO: These are messy
*/
((Preference) findPreference("overlap1")).setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
boolean isChecked = (Boolean) newValue;
if (isChecked) {
prefs.edit().putInt("type", LayoutParams.TYPE_SYSTEM_OVERLAY).commit();
if (prefs.getBoolean("overlap2", false))
prefs.edit().putInt("flags", LayoutParams.FLAG_SHOW_WHEN_LOCKED | LayoutParams.FLAG_LAYOUT_IN_SCREEN).commit();
else
prefs.edit().putInt("flags", LayoutParams.FLAG_SHOW_WHEN_LOCKED).commit();
} else {
prefs.edit().putInt("type", LayoutParams.TYPE_SYSTEM_ALERT).commit();
if (prefs.getBoolean("overlap2", false))
prefs.edit().putInt("flags", LayoutParams.FLAG_NOT_TOUCH_MODAL | LayoutParams.FLAG_LAYOUT_IN_SCREEN).commit();
else
prefs.edit().putInt("flags", LayoutParams.FLAG_NOT_TOUCH_MODAL).commit();
}
new Thread(new Runnable() {
@Override
public void run() {
// Disable and Re-enable the corners
StandOutWindow.closeAll(SettingsActivity.this, Corner.class);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
StandOutWindow.show(SettingsActivity.this, Corner.class, 0);
StandOutWindow.show(SettingsActivity.this, Corner.class, 1);
StandOutWindow.show(SettingsActivity.this, Corner.class, 2);
StandOutWindow.show(SettingsActivity.this, Corner.class, 3);
}
}).start();
return true;
}
});
((Preference) findPreference("overlap2")).setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
boolean isChecked = (Boolean) newValue;
if (isChecked) {
if (prefs.getBoolean("overlap", true))
prefs.edit().putInt("flags", LayoutParams.FLAG_SHOW_WHEN_LOCKED | LayoutParams.FLAG_LAYOUT_IN_SCREEN).commit();
else
prefs.edit().putInt("flags", LayoutParams.FLAG_NOT_TOUCH_MODAL | LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH | LayoutParams.FLAG_LAYOUT_IN_SCREEN).commit();
} else {
if (prefs.getBoolean("overlap", true))
prefs.edit().putInt("flags", LayoutParams.FLAG_SHOW_WHEN_LOCKED).commit();
else
prefs.edit().putInt("flags", LayoutParams.FLAG_NOT_TOUCH_MODAL | LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH).commit();
}
new Thread(new Runnable() {
@Override
public void run() {
// Disable and Reenable the corners
StandOutWindow.closeAll(SettingsActivity.this, Corner.class);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
StandOutWindow.show(SettingsActivity.this, Corner.class, 0);
StandOutWindow.show(SettingsActivity.this, Corner.class, 1);
StandOutWindow.show(SettingsActivity.this, Corner.class, 2);
StandOutWindow.show(SettingsActivity.this, Corner.class, 3);
}
}).start();
return true;
}
});
/**
* TODO: Figure out if Developer Options is enabled. If so, show a
* GitHub Source Code Link preference:
* "Seems like you are a developer? Check out the RoundR source code on GitHub!"
*/
}
/*
* Sends a signal to all the corners to refresh their layout parameters,
* which in turn refreshes their size.
*/
public void refresh() {
StandOutWindow.sendData(this, Corner.class, Corner.wildcard, Corner.UPDATE_CODE, new Bundle(), Corner.class, StandOutWindow.DISREGARD_ID);
}
@SuppressLint("InlinedApi")
public void showInstalledAppDetails(String packageName) {
Intent intent = new Intent();
intent.setAction(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", packageName, null);
intent.setData(uri);
startActivity(intent);
}
}
preferences.xml:
Code:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:roundr="roundrprefs" >
<PreferenceCategory android:title="General Settings" >
<CheckBoxPreference
android:defaultValue="true"
android:key="enable"
android:summary="Enable rounded screen corners"
android:title="Enable RoundR" />
<CheckBoxPreference
android:defaultValue="true"
android:key="start_on_boot"
android:summary="Start RoundR automatically on boot"
android:title="Start on boot" />
<CheckBoxPreference
android:defaultValue="true"
android:key="notification"
android:summary="The notification is required to keep RoundR running in low memory situations"
android:title="Visible Notification" />
</PreferenceCategory>
<PreferenceCategory android:title="RoundR Settings" >
<PreferenceScreen
android:dependency="enable"
android:persistent="false"
android:summary="Enable rounding on specific corners"
android:title="Enabled Corners" >
<CheckBoxPreference
android:defaultValue="true"
android:key="corner0"
android:title="Top Left" />
<CheckBoxPreference
android:defaultValue="true"
android:key="corner1"
android:title="Top Right" />
<CheckBoxPreference
android:defaultValue="true"
android:key="corner2"
android:title="Bottom Left" />
<CheckBoxPreference
android:defaultValue="true"
android:key="corner3"
android:title="Bottom Right" />
</PreferenceScreen>
<mohammad.adib.roundr.SeekBarPreference
android:defaultValue="10"
android:key="radius"
android:max="40"
android:title="Corner Radius"
roundr:min="2"
roundr:unitsLeft=""
roundr:unitsRight="" />
<CheckBoxPreference
android:defaultValue="true"
android:key="overlap1"
android:summary="This also constitutes overlaping of the corners on the notification pull-down"
android:title="Enable on lockscreen" />
<CheckBoxPreference
android:defaultValue="false"
android:key="overlap2"
android:summary="Allows for the corners to overlap the status bar"
android:title="Overlap Status Bar" />
</PreferenceCategory>
</PreferenceScreen>
Can u help me? where is the specific code that i need, i was trying to find it for hours...
Enviado desde mi GT-S5570I usando Tapatalk 2
DannyGM16 said:
I don't find the code that I need, Help me please.
This is the code:
MainActivity.java:
Code:
package mohammad.adib.roundr;
/**
* Copyright 2013 Mohammad Adib
*
* 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.
*/
import wei.mark.standout.StandOutWindow;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
public class MainActivity extends Activity {
/**
* Main Activity that launches the 4 floating windows (corners)
*
* @author Mohammad Adib <[email protected]>
*
* Contributors: Mark Wei
*
*/
ProgressDialog progress;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
if (!BootReceiver.boot_up || Corner.running) {
Intent i = new Intent(this, SettingsActivity.class);
startActivity(i);
}
if (prefs.getBoolean("enable", true)) {
StandOutWindow.show(this, Corner.class, 0);
StandOutWindow.show(this, Corner.class, 1);
StandOutWindow.show(this, Corner.class, 2);
StandOutWindow.show(this, Corner.class, 3);
}
finish();
}
}
Corner.java:
Code:
package mohammad.adib.roundr;
/**
* Copyright 2013 Mohammad Adib
*
* 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.
*/
import wei.mark.standout.StandOutWindow;
import wei.mark.standout.constants.StandOutFlags;
import wei.mark.standout.ui.Window;
import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.RemoteViews;
public class Corner extends StandOutWindow {
/**
* The individual floating window that sits at one of the corners of the
* screen. Window ID corresponds to which corner this goes to.
*
* @author Mohammad Adib <[email protected]>
*
* Contributors: Mark Wei, Jan Metten
*
*/
public static final String ACTION_SETTINGS = "SETTINGS";
public static final String BCAST_CONFIGCHANGED = "android.intent.action.CONFIGURATION_CHANGED";
public static final int UPDATE_CODE = 2;
public static final int NOTIFICATION_CODE = 3;
public static final int wildcard = 0;
private SharedPreferences prefs;
public static boolean running = false;
@Override
public String getAppName() {
return "RoundR";
}
@Override
public int getAppIcon() {
return R.drawable.notif_icon;
}
@Override
public void createAndAttachView(int corner, FrameLayout frame) {
// Set the image based on window corner
LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
ImageView v = (ImageView) inflater.inflate(R.layout.corner, frame, true).findViewById(R.id.iv);
// Top left by default
v.setImageDrawable(getResources().getDrawable(R.drawable.topleft));
switch (corner) {
case 1:
v.setImageDrawable(getResources().getDrawable(R.drawable.topright));
break;
case 2:
v.setImageDrawable(getResources().getDrawable(R.drawable.bottomleft));
break;
case 3:
v.setImageDrawable(getResources().getDrawable(R.drawable.bottomright));
break;
}
}
private int pxFromDp(double dp) {
return (int) (dp * getResources().getDisplayMetrics().density);
}
/**
* Corners: 0 = top left; 1 = top right; 2 = bottom left; 3 = bottom right;
*/
@Override
public StandOutLayoutParams getParams(int corner, Window window) {
prefs = PreferenceManager.getDefaultSharedPreferences(this);
// Check if this corner is enabled
if (prefs.getBoolean("corner" + corner, true)) {
int radius = pxFromDp(prefs.getInt("radius", 20));
// Thanks to Jan Metten for rewriting this based on gravity
switch (corner) {
case 0:
return new StandOutLayoutParams(corner, radius, radius, Gravity.TOP | Gravity.LEFT);
case 1:
return new StandOutLayoutParams(corner, radius, radius, Gravity.TOP | Gravity.RIGHT);
case 2:
return new StandOutLayoutParams(corner, radius, radius, Gravity.BOTTOM | Gravity.LEFT);
case 3:
return new StandOutLayoutParams(corner, radius, radius, Gravity.BOTTOM | Gravity.RIGHT);
}
}
// Outside of screen
return new StandOutLayoutParams(corner, 1, 1, -1, -1, 1, 1);
}
@Override
public int getFlags(int corner) {
return super.getFlags(corner) | StandOutFlags.FLAG_WINDOW_FOCUSABLE_DISABLE | StandOutFlags.FLAG_WINDOW_EDGE_LIMITS_ENABLE;
}
@Override
public String getPersistentNotificationMessage(int corner) {
return "Tap to configure";
}
@Override
public Intent getPersistentNotificationIntent(int corner) {
return new Intent(this, Corner.class).putExtra("id", corner).setAction(ACTION_SETTINGS);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null) {
String action = intent.getAction();
int corner = intent.getIntExtra("id", DEFAULT_ID);
if (corner == ONGOING_NOTIFICATION_ID) {
throw new RuntimeException("ID cannot equals StandOutWindow.ONGOING_NOTIFICATION_ID");
}
if (ACTION_SHOW.equals(action) || ACTION_RESTORE.equals(action)) {
show(corner);
} else if (ACTION_SETTINGS.equals(action)) {
try {
Intent intentS = new Intent(this, SettingsActivity.class);
intentS.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intentS);
} catch (Exception e) {
// Addressing this issue: http://i.imgur.com/Op9kfy8.png
}
} else if (ACTION_HIDE.equals(action)) {
hide(corner);
} else if (ACTION_CLOSE.equals(action)) {
close(corner);
} else if (ACTION_CLOSE_ALL.equals(action)) {
closeAll();
} else if (ACTION_SEND_DATA.equals(action)) {
if (isExistingId(corner) || corner == DISREGARD_ID) {
Bundle data = intent.getBundleExtra("wei.mark.standout.data");
int requestCode = intent.getIntExtra("requestCode", 0);
@SuppressWarnings("unchecked")
Class<? extends StandOutWindow> fromCls = (Class<? extends StandOutWindow>) intent.getSerializableExtra("wei.mark.standout.fromCls");
int fromId = intent.getIntExtra("fromId", DEFAULT_ID);
onReceiveData(corner, requestCode, data, fromCls, fromId);
}
}
}
return START_NOT_STICKY;
}
@Override
public boolean onClose(final int corner, final Window window) {
running = false;
return false;
}
@Override
public String getPersistentNotificationTitle(int corner) {
return "Rounded Corners";
}
@SuppressLint({ "InlinedApi", "NewApi" })
@SuppressWarnings("deprecation")
@Override
public Notification getPersistentNotification(int id) {
int icon = getAppIcon();
long when = System.currentTimeMillis();
Context c = getApplicationContext();
String contentTitle = getPersistentNotificationTitle(id);
String contentText = getPersistentNotificationMessage(id);
Intent notificationIntent = getPersistentNotificationIntent(id);
PendingIntent contentIntent = PendingIntent.getService(this, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
// 4.1+ Low priority notification
final int apiLevel = Build.VERSION.SDK_INT;
if (apiLevel >= 16) {
Notification.Builder mBuilder = new Notification.Builder(this).setContent(new RemoteViews(getPackageName(), R.layout.notification)).setSmallIcon(getAppIcon()).setContentTitle(contentTitle).setContentText(contentText).setPriority(Notification.PRIORITY_MIN).setContentIntent(contentIntent);
return mBuilder.build();
}
String tickerText = String.format("%s: %s", contentTitle, contentText);
Notification notification = new Notification(icon, tickerText, when);
notification.setLatestEventInfo(c, contentTitle, contentText, contentIntent);
return notification;
}
@Override
public boolean onShow(final int corner, final Window window) {
running = true;
return false;
}
@Override
public void onReceiveData(int corner, int requestCode, Bundle data, Class<? extends StandOutWindow> fromCls, int fromId) {
Window window = getWindow(corner);
if (requestCode == UPDATE_CODE) {
// Update the corners when device is rotated
updateViewLayout(3, getParams(3, window));
updateViewLayout(2, getParams(2, window));
updateViewLayout(1, getParams(1, window));
updateViewLayout(0, getParams(0, window));
} else if (requestCode == NOTIFICATION_CODE) {
if (!prefs.getBoolean("notification", true)) {
// Hide Notification Icon (for <= Gingerbread devices only)
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = getPersistentNotification(corner);
notification.icon = wei.mark.standout.R.drawable.nothing;
mNotificationManager.notify(getClass().hashCode() + ONGOING_NOTIFICATION_ID, notification);
Log.d("Hello World", "");
} else {
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = getPersistentNotification(corner);
mNotificationManager.notify(getClass().hashCode() + ONGOING_NOTIFICATION_ID, notification);
}
}
}
}
SeekBarPreference:
Code:
package mohammad.adib.roundr;
import wei.mark.standout.StandOutWindow;
import android.content.Context;
import android.content.res.TypedArray;
import android.os.Bundle;
import android.preference.Preference;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
public class SeekBarPreference extends Preference implements OnSeekBarChangeListener {
private final String TAG = getClass().getName();
private static final String ANDROIDNS = "http://schemas.android.com/apk/res/android";
private static final String ROUNDRNS = "roundrprefs";
private static final int DEFAULT_VALUE = 50;
private int mMaxValue = 100;
private int mMinValue = 0;
private int mInterval = 1;
private int mCurrentValue;
private String mUnitsLeft = "";
private String mUnitsRight = "";
private SeekBar mSeekBar;
private Context context;
private TextView mStatusText;
public SeekBarPreference(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
initPreference(context, attrs);
}
public SeekBarPreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initPreference(context, attrs);
}
private void initPreference(Context context, AttributeSet attrs) {
setValuesFromXml(attrs);
mSeekBar = new SeekBar(context, attrs);
mSeekBar.setMax(mMaxValue - mMinValue);
mSeekBar.setOnSeekBarChangeListener(this);
}
private void setValuesFromXml(AttributeSet attrs) {
mMaxValue = attrs.getAttributeIntValue(ANDROIDNS, "max", 100);
mMinValue = attrs.getAttributeIntValue(ROUNDRNS, "min", 0);
mUnitsLeft = getAttributeStringValue(attrs, ROUNDRNS, "unitsLeft", "");
String units = getAttributeStringValue(attrs, ROUNDRNS, "units", "");
mUnitsRight = getAttributeStringValue(attrs, ROUNDRNS, "unitsRight", units);
try {
String newInterval = attrs.getAttributeValue(ROUNDRNS, "interval");
if (newInterval != null)
mInterval = Integer.parseInt(newInterval);
} catch (Exception e) {
Log.e(TAG, "Invalid interval value", e);
}
}
private String getAttributeStringValue(AttributeSet attrs, String namespace, String name, String defaultValue) {
String value = attrs.getAttributeValue(namespace, name);
if (value == null)
value = defaultValue;
return value;
}
@Override
protected View onCreateView(ViewGroup parent) {
RelativeLayout layout = null;
try {
LayoutInflater mInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
layout = (RelativeLayout) mInflater.inflate(R.layout.seek_bar_preference, parent, false);
} catch (Exception e) {
Log.e(TAG, "Error creating seek bar preference", e);
}
return layout;
}
@Override
public void onBindView(View view) {
super.onBindView(view);
try {
// move our seekbar to the new view we've been given
ViewParent oldContainer = mSeekBar.getParent();
ViewGroup newContainer = (ViewGroup) view.findViewById(R.id.seekBarPrefBarContainer);
if (oldContainer != newContainer) {
// remove the seekbar from the old view
if (oldContainer != null) {
((ViewGroup) oldContainer).removeView(mSeekBar);
}
// remove the existing seekbar (there may not be one) and add
// ours
newContainer.removeAllViews();
newContainer.addView(mSeekBar, ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
}
} catch (Exception ex) {
Log.e(TAG, "Error binding view: " + ex.toString());
}
updateView(view);
}
/**
* Update a SeekBarPreference view with our current state
*
* @param view
*/
protected void updateView(View view) {
try {
RelativeLayout layout = (RelativeLayout) view;
mStatusText = (TextView) layout.findViewById(R.id.seekBarPrefValue);
mStatusText.setText(String.valueOf(pxFromDp(mCurrentValue)));
mStatusText.setMinimumWidth(30);
mSeekBar.setProgress(mCurrentValue - mMinValue);
} catch (Exception e) {
Log.e(TAG, "Error updating seek bar preference", e);
}
}
private int pxFromDp(double dp) {
return (int) (dp * context.getResources().getDisplayMetrics().density);
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
int newValue = progress + mMinValue;
if (newValue > mMaxValue)
newValue = mMaxValue;
else if (newValue < mMinValue)
newValue = mMinValue;
else if (mInterval != 1 && newValue % mInterval != 0)
newValue = Math.round(((float) newValue) / mInterval) * mInterval;
// change rejected, revert to the previous value
if (!callChangeListener(newValue)) {
seekBar.setProgress(mCurrentValue - mMinValue);
return;
}
// change accepted, store it
mCurrentValue = newValue;
mStatusText.setText(String.valueOf(pxFromDp(newValue)));
persistInt(newValue);
// Refresh the corners to apply the new radius
StandOutWindow.sendData(context, Corner.class, Corner.wildcard, Corner.UPDATE_CODE, new Bundle(), Corner.class, StandOutWindow.DISREGARD_ID);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
notifyChanged();
}
@Override
protected Object onGetDefaultValue(TypedArray ta, int index) {
int defaultValue = ta.getInt(index, DEFAULT_VALUE);
return defaultValue;
}
@Override
protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
if (restoreValue) {
mCurrentValue = getPersistedInt(mCurrentValue);
} else {
int temp = 0;
try {
temp = (Integer) defaultValue;
} catch (Exception ex) {
Log.e(TAG, "Invalid default value: " + defaultValue.toString());
}
persistInt(temp);
mCurrentValue = temp;
}
}
}
SettingsActivity.java:
Code:
package mohammad.adib.roundr;
import wei.mark.standout.StandOutWindow;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.preference.Preference;
import android.preference.PreferenceManager;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceActivity;
import android.util.Log;
import android.view.WindowManager.LayoutParams;
public class SettingsActivity extends PreferenceActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
/**
* Handle Preference Changes
*/
// Enable/Disable
((Preference) findPreference("enable")).setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
boolean isChecked = (Boolean) newValue;
if (isChecked) {
StandOutWindow.show(SettingsActivity.this, Corner.class, 0);
StandOutWindow.show(SettingsActivity.this, Corner.class, 1);
StandOutWindow.show(SettingsActivity.this, Corner.class, 2);
StandOutWindow.show(SettingsActivity.this, Corner.class, 3);
} else {
StandOutWindow.closeAll(SettingsActivity.this, Corner.class);
}
return true;
}
});
// Notification
final int apiLevel = Build.VERSION.SDK_INT;
if (apiLevel >= 16) {
((Preference) findPreference("notification")).setOnPreferenceClickListener(new OnPreferenceClickListener() {
public boolean onPreferenceClick(Preference preference) {
new AlertDialog.Builder(SettingsActivity.this).setTitle("Notification").setMessage("The notification prevents Android from killing RoundR in low memory situations.\n\nOn Android 4.1+ devices, it can be disabled via the App Info.").setPositiveButton("Continue", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
showInstalledAppDetails("mohammad.adib.roundr");
}
}).show();
return true;
}
});
}else{
((Preference) findPreference("notification")).setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
StandOutWindow.sendData(SettingsActivity.this, Corner.class, Corner.wildcard, Corner.NOTIFICATION_CODE, new Bundle(), Corner.class, StandOutWindow.DISREGARD_ID);
return true;
}
});
}
// Enable specific corners
for (int i = 0; i < 4; i++) {
((Preference) findPreference("corner" + i)).setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
refresh();
return true;
}
});
}
/**
* Overlap Settings TODO: These are messy
*/
((Preference) findPreference("overlap1")).setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
boolean isChecked = (Boolean) newValue;
if (isChecked) {
prefs.edit().putInt("type", LayoutParams.TYPE_SYSTEM_OVERLAY).commit();
if (prefs.getBoolean("overlap2", false))
prefs.edit().putInt("flags", LayoutParams.FLAG_SHOW_WHEN_LOCKED | LayoutParams.FLAG_LAYOUT_IN_SCREEN).commit();
else
prefs.edit().putInt("flags", LayoutParams.FLAG_SHOW_WHEN_LOCKED).commit();
} else {
prefs.edit().putInt("type", LayoutParams.TYPE_SYSTEM_ALERT).commit();
if (prefs.getBoolean("overlap2", false))
prefs.edit().putInt("flags", LayoutParams.FLAG_NOT_TOUCH_MODAL | LayoutParams.FLAG_LAYOUT_IN_SCREEN).commit();
else
prefs.edit().putInt("flags", LayoutParams.FLAG_NOT_TOUCH_MODAL).commit();
}
new Thread(new Runnable() {
@Override
public void run() {
// Disable and Re-enable the corners
StandOutWindow.closeAll(SettingsActivity.this, Corner.class);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
StandOutWindow.show(SettingsActivity.this, Corner.class, 0);
StandOutWindow.show(SettingsActivity.this, Corner.class, 1);
StandOutWindow.show(SettingsActivity.this, Corner.class, 2);
StandOutWindow.show(SettingsActivity.this, Corner.class, 3);
}
}).start();
return true;
}
});
((Preference) findPreference("overlap2")).setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
boolean isChecked = (Boolean) newValue;
if (isChecked) {
if (prefs.getBoolean("overlap", true))
prefs.edit().putInt("flags", LayoutParams.FLAG_SHOW_WHEN_LOCKED | LayoutParams.FLAG_LAYOUT_IN_SCREEN).commit();
else
prefs.edit().putInt("flags", LayoutParams.FLAG_NOT_TOUCH_MODAL | LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH | LayoutParams.FLAG_LAYOUT_IN_SCREEN).commit();
} else {
if (prefs.getBoolean("overlap", true))
prefs.edit().putInt("flags", LayoutParams.FLAG_SHOW_WHEN_LOCKED).commit();
else
prefs.edit().putInt("flags", LayoutParams.FLAG_NOT_TOUCH_MODAL | LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH).commit();
}
new Thread(new Runnable() {
@Override
public void run() {
// Disable and Reenable the corners
StandOutWindow.closeAll(SettingsActivity.this, Corner.class);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
StandOutWindow.show(SettingsActivity.this, Corner.class, 0);
StandOutWindow.show(SettingsActivity.this, Corner.class, 1);
StandOutWindow.show(SettingsActivity.this, Corner.class, 2);
StandOutWindow.show(SettingsActivity.this, Corner.class, 3);
}
}).start();
return true;
}
});
/**
* TODO: Figure out if Developer Options is enabled. If so, show a
* GitHub Source Code Link preference:
* "Seems like you are a developer? Check out the RoundR source code on GitHub!"
*/
}
/*
* Sends a signal to all the corners to refresh their layout parameters,
* which in turn refreshes their size.
*/
public void refresh() {
StandOutWindow.sendData(this, Corner.class, Corner.wildcard, Corner.UPDATE_CODE, new Bundle(), Corner.class, StandOutWindow.DISREGARD_ID);
}
@SuppressLint("InlinedApi")
public void showInstalledAppDetails(String packageName) {
Intent intent = new Intent();
intent.setAction(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", packageName, null);
intent.setData(uri);
startActivity(intent);
}
}
preferences.xml:
Code:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:roundr="roundrprefs" >
<PreferenceCategory android:title="General Settings" >
<CheckBoxPreference
android:defaultValue="true"
android:key="enable"
android:summary="Enable rounded screen corners"
android:title="Enable RoundR" />
<CheckBoxPreference
android:defaultValue="true"
android:key="start_on_boot"
android:summary="Start RoundR automatically on boot"
android:title="Start on boot" />
<CheckBoxPreference
android:defaultValue="true"
android:key="notification"
android:summary="The notification is required to keep RoundR running in low memory situations"
android:title="Visible Notification" />
</PreferenceCategory>
<PreferenceCategory android:title="RoundR Settings" >
<PreferenceScreen
android:dependency="enable"
android:persistent="false"
android:summary="Enable rounding on specific corners"
android:title="Enabled Corners" >
<CheckBoxPreference
android:defaultValue="true"
android:key="corner0"
android:title="Top Left" />
<CheckBoxPreference
android:defaultValue="true"
android:key="corner1"
android:title="Top Right" />
<CheckBoxPreference
android:defaultValue="true"
android:key="corner2"
android:title="Bottom Left" />
<CheckBoxPreference
android:defaultValue="true"
android:key="corner3"
android:title="Bottom Right" />
</PreferenceScreen>
<mohammad.adib.roundr.SeekBarPreference
android:defaultValue="10"
android:key="radius"
android:max="40"
android:title="Corner Radius"
roundr:min="2"
roundr:unitsLeft=""
roundr:unitsRight="" />
<CheckBoxPreference
android:defaultValue="true"
android:key="overlap1"
android:summary="This also constitutes overlaping of the corners on the notification pull-down"
android:title="Enable on lockscreen" />
<CheckBoxPreference
android:defaultValue="false"
android:key="overlap2"
android:summary="Allows for the corners to overlap the status bar"
android:title="Overlap Status Bar" />
</PreferenceCategory>
</PreferenceScreen>
Can u help me? where is the specific code that i need, i was trying to find it for hours...
Enviado desde mi GT-S5570I usando Tapatalk 2
Click to expand...
Click to collapse
It's this particular code change: https://github.com/MohammadAdib/Roundr/commit/b47ca72867093dbe9b29a99469f48e95a1d369fa
nikwen said:
It's this particular code change: https://github.com/MohammadAdib/Roundr/commit/b47ca72867093dbe9b29a99469f48e95a1d369fa
Click to expand...
Click to collapse
IT WORK'S! IT WORK'S! THANK'S!
But the problem now i how to get clicks from it. Do you know how to do it?
Enviado desde mi GT-S5570I usando Tapatalk 2
DannyGM16 said:
IT WORK'S! IT WORK'S! THANK'S!
But the problem now i how to get clicks from it. Do you know how to do it?
Enviado desde mi GT-S5570I usando Tapatalk 2
Click to expand...
Click to collapse
Great. :good:
What's about adding an onClick listener?
nikwen said:
Great. :good:
What's about adding an onClick listener?
Click to expand...
Click to collapse
I tryed it, but the onClick affects to all the screen...
Enviado desde mi GT-S5570I usando Tapatalk 2

[Tutorial] Create a Running Man Game Animation on Android

Hello,
I create that thread to present you a tutorial aiming to learn you how to create a Running Man Game Animation on Android. You can discover the tutorial in video on Youtube :
Create a Running Man Game Animation on Android
Making a Running Man Animation on Android is a great way to learn how to work with Bitmaps, Thread and SurfaceView. First thing to make a Running Man Game Animation is to have a character to animate. For that, we will use the following sprite sheet :
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
Like you can see, our character sprite sheet has 8 frames. Each frame show the character in a different position when he runs.
For our animation, we are going to create a custom GameView extending the SurfaceView class and implementing the Runnable interface. First, we need to define some properties like the game thread, the surface holder, the canvas where running man will be drawn, the bitmap used to load the sprite sheet and some parameters to customize the running man animation like the speed, the size or the position of the man on the screen :
Code:
class GameView extends SurfaceView implements Runnable {
private Thread gameThread;
private SurfaceHolder ourHolder;
private volatile boolean playing;
private Canvas canvas;
private Bitmap bitmapRunningMan;
private boolean isMoving;
private float runSpeedPerSecond = 500;
private float manXPos = 10, manYPos = 10;
private int frameWidth = 230, frameHeight = 274;
private int frameCount = 8;
private int currentFrame = 0;
private long fps;
private long timeThisFrame;
private long lastFrameChangeTime = 0;
private int frameLengthInMillisecond = 50;
// ...
}
To draw correctly the good frame for the running man, we need two Rectangle instances. One used to define the current frame in the sprite sheet and an other to define where to draw the current frame on the screen :
Code:
private Rect frameToDraw = new Rect(0, 0, frameWidth, frameHeight);
private RectF whereToDraw = new RectF(manXPos, manYPos,
manXPos + frameWidth, frameHeight);
On the GameView constructor, we get the surface holder and then, we load the sprite sheet into the bitmapRunningMan variable. We apply a scale transformation according values defined in frameWidth and frameHeight parameters :
Code:
public GameView(Context context) {
super(context);
ourHolder = getHolder();
bitmapRunningMan = BitmapFactory.decodeResource(getResources(),
R.drawable.running_man);
bitmapRunningMan = Bitmap.createScaledBitmap(bitmapRunningMan,
frameWidth * frameCount, frameHeight, false);
}
Now, it's time to make the event loop for animation inside the run method overrided from Runnable interface :
Code:
@Override
public void run() {
while (playing) {
long startFrameTime = System.currentTimeMillis();
update();
draw();
timeThisFrame = System.currentTimeMillis() - startFrameTime;
if (timeThisFrame >= 1) {
fps = 1000 / timeThisFrame;
}
}
}
Note that we animate the character while the playing variable is set to true. Like usual in a game, we update the elements and then we draw before to calculate frame per seconds. The update method is just used here to move the man positions in X and Y. Note that when the man reach the end of the screen horizontally or vertically, we set its position to the left or top of the screen :
Code:
public void update() {
if (isMoving) {
manXPos = manXPos + runSpeedPerSecond / fps;
if (manXPos > getWidth()) {
manYPos += (int) frameHeight;
manXPos = 10;
}
if (manYPos + frameHeight > getHeight()) {
manYPos = 10;
}
}
}
Before to write the draw method, we need to define a method to manage the current frame to display for the character. We change the current frame only when he have ended the frame duration :
Code:
public void manageCurrentFrame() {
long time = System.currentTimeMillis();
if (isMoving) {
if (time > lastFrameChangeTime + frameLengthInMillisecond) {
lastFrameChangeTime = time;
currentFrame++;
if (currentFrame >= frameCount) {
currentFrame = 0;
}
}
}
frameToDraw.left = currentFrame * frameWidth;
frameToDraw.right = frameToDraw.left + frameWidth;
}
And now, we define the draw method :
Code:
public void draw() {
if (ourHolder.getSurface().isValid()) {
canvas = ourHolder.lockCanvas();
canvas.drawColor(Color.WHITE);
whereToDraw.set((int) manXPos, (int) manYPos, (int) manXPos
+ frameWidth, (int) manYPos + frameHeight);
manageCurrentFrame();
canvas.drawBitmap(bitmapRunningMan, frameToDraw, whereToDraw, null);
ourHolder.unlockCanvasAndPost(canvas);
}
}
First, we check if the surface is valid. Then we lock the canvas and we draw the character current frame. Last, we unlock the canvas and post it on the Surface View. Finally, we define two methods to pause or resume the running man animation :
Code:
public void pause() {
playing = false;
try {
gameThread.join();
} catch(InterruptedException e) {
Log.e("ERR", "Joining Thread");
}
}
public void resume() {
playing = true;
gameThread = new Thread(this);
gameThread.start();
}
To start the running man animation, we're going to wait the user click on the surface view. So, we need to override the onTouchEvent method and wait for an ACTION_DOWN event. When the event is made, we have just to change the isMoving boolean value. If man is running, we stop it. If man doesn't run, we start to move it :
Code:
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN :
isMoving = !isMoving;
break;
}
return true;
}
Last thing to make is to assemble all the pieces of the puzzle, create the game view on the main activity, set it as the content view and then resume or pause the game animation when the activity is resumed or paused :
Code:
package com.ssaurel.runningman;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class RunningManAnimation extends AppCompatActivity {
private GameView gameView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
gameView = new GameView(this);
setContentView(gameView);
}
@Override
protected void onResume() {
super.onResume();
gameView.resume();
}
@Override
protected void onPause() {
super.onPause();
gameView.pause();
}
class GameView extends SurfaceView implements Runnable {
private Thread gameThread;
private SurfaceHolder ourHolder;
private volatile boolean playing;
private Canvas canvas;
private Bitmap bitmapRunningMan;
private boolean isMoving;
private float runSpeedPerSecond = 500;
private float manXPos = 10, manYPos = 10;
private int frameWidth = 230, frameHeight = 274;
private int frameCount = 8;
private int currentFrame = 0;
private long fps;
private long timeThisFrame;
private long lastFrameChangeTime = 0;
private int frameLengthInMillisecond = 50;
private Rect frameToDraw = new Rect(0, 0, frameWidth, frameHeight);
private RectF whereToDraw = new RectF(manXPos, manYPos, manXPos + frameWidth, frameHeight);
public GameView(Context context) {
super(context);
ourHolder = getHolder();
bitmapRunningMan = BitmapFactory.decodeResource(getResources(), R.drawable.running_man);
bitmapRunningMan = Bitmap.createScaledBitmap(bitmapRunningMan, frameWidth * frameCount, frameHeight, false);
}
@Override
public void run() {
while (playing) {
long startFrameTime = System.currentTimeMillis();
update();
draw();
timeThisFrame = System.currentTimeMillis() - startFrameTime;
if (timeThisFrame >= 1) {
fps = 1000 / timeThisFrame;
}
}
}
public void update() {
if (isMoving) {
manXPos = manXPos + runSpeedPerSecond / fps;
if (manXPos > getWidth()) {
manYPos += (int) frameHeight;
manXPos = 10;
}
if (manYPos + frameHeight > getHeight()) {
manYPos = 10;
}
}
}
public void manageCurrentFrame() {
long time = System.currentTimeMillis();
if (isMoving) {
if (time > lastFrameChangeTime + frameLengthInMillisecond) {
lastFrameChangeTime = time;
currentFrame++;
if (currentFrame >= frameCount) {
currentFrame = 0;
}
}
}
frameToDraw.left = currentFrame * frameWidth;
frameToDraw.right = frameToDraw.left + frameWidth;
}
public void draw() {
if (ourHolder.getSurface().isValid()) {
canvas = ourHolder.lockCanvas();
canvas.drawColor(Color.WHITE);
whereToDraw.set((int) manXPos, (int) manYPos, (int) manXPos + frameWidth, (int) manYPos + frameHeight);
manageCurrentFrame();
canvas.drawBitmap(bitmapRunningMan, frameToDraw, whereToDraw, null);
ourHolder.unlockCanvasAndPost(canvas);
}
}
public void pause() {
playing = false;
try {
gameThread.join();
} catch(InterruptedException e) {
Log.e("ERR", "Joining Thread");
}
}
public void resume() {
playing = true;
gameThread = new Thread(this);
gameThread.start();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN :
isMoving = !isMoving;
break;
}
return true;
}
}
}
Now, you have just to run the application on your Android emulator or on your real device and to enjoy your Running Man Game Animation.
Don't hesitate to try this code and give me your feedbacks.
Thanks.
Sylvain
I just started learning self taught Android development and hopefully, I get to this level one days. Thanks for sharing your steps for this
Sent from my Nexus 6P using Tapatalk
nighthawk626 said:
I just started learning self taught Android development and hopefully, I get to this level one days. Thanks for sharing your steps for this
Sent from my Nexus 6P using Tapatalk
Click to expand...
Click to collapse
Great . I plan to make some tutorials for beginners too. Do you have some suggestions for that kind of tutorials ?
No suggestions, I'm just looking for a good place to begin. I first started with Android development then I scaled back to learn about Java, and still no luck, so I just started off with c++. Lol
Sent from my Nexus 6P using Tapatalk

Categories

Resources