[Q] How to call an mothod from another class using an service - Java for Android App Development

Hello xda,
I have the following code into the MainActivity to figure out the orientation of the device:
Code:
public int getScreenOrientation() {
int rotation = getWindowManager().getDefaultDisplay().getRotation();
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
int width = dm.widthPixels;
int height = dm.heightPixels;
int orientation=0;
// if the device's natural orientation is portrait:
if ((rotation == Surface.ROTATION_0
|| rotation == Surface.ROTATION_180) && height > width ||
(rotation == Surface.ROTATION_90
|| rotation == Surface.ROTATION_270) && width > height) {
switch(rotation) {
case Surface.ROTATION_0:
//orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
Toast.makeText(getApplicationContext(),"portrait",Toast.LENGTH_SHORT ).show();
break;
case Surface.ROTATION_90:
Toast.makeText(getApplicationContext(),"landscape",Toast.LENGTH_SHORT ).show();
break;
case Surface.ROTATION_180:
Toast.makeText(getApplicationContext(),"reverse portrait",Toast.LENGTH_SHORT ).show();
break;
case Surface.ROTATION_270:
Toast.makeText(getApplicationContext(),"reverse landscape",Toast.LENGTH_SHORT ).show();
break;
default:
Toast.makeText(getApplicationContext(),"portrait",Toast.LENGTH_SHORT ).show();
break;
}
}
// if the device's natural orientation is landscape or if the device
// is square:
else {
switch(rotation) {
case Surface.ROTATION_0:
Toast.makeText(getApplicationContext(),"landscape",Toast.LENGTH_SHORT ).show();
break;
case Surface.ROTATION_90:
Toast.makeText(getApplicationContext(),"portrait",Toast.LENGTH_SHORT ).show();
break;
case Surface.ROTATION_180:
Toast.makeText(getApplicationContext(),"reverse landscape",Toast.LENGTH_SHORT ).show();
break;
case Surface.ROTATION_270:
Toast.makeText(getApplicationContext(),"reverse portrait",Toast.LENGTH_SHORT ).show();
break;
default:
Toast.makeText(getApplicationContext(),"landscape",Toast.LENGTH_SHORT ).show();
break;
}
}
return orientation;
}
I created an service that runs in background and overrided OnConfigurationChanged so that i can call getScreenOrientation whenever the device orientation is changed.
I tried to call the method using, but the app crashes:
Code:
MainActivity main = new MainActivity();
main.getScreenOrientation();
I tried to implement getScreenOrientation right in the service class but it says "Cannot resolve method getWindowManager()"
Can someone help me out? Or is any other way I can accomplish this?
Thanks!!

Try using this to get it directly from your service:
Code:
window = (WindowManager) getSystemService(Context.WINDOW_SERVICE);

zalez said:
Try using this to get it directly from your service:
Code:
window = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
Click to expand...
Click to collapse
thanks!! It worked flawlessly...Although it's strange that I can't call the method...

Related

Detect when phone in use

Is it possible to programmatically detect when telephone is in use on XDA2, and if so how? Examples using API calls would be great as our app is developed in eVB3 and eVC3.
Thanks
Hi,
You can use the ConnectionManager api and make the connection asyncrous so your main window will be notified with connection events, for example, when the event is received do something like this:
LRESULT DoCommMgrEventMain(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam) {
DWORD dwStatus;
ConnMgrConnectionStatus(hConnection, &dwStatus);
switch(dwStatus) {
case CONNMGR_STATUS_UNKNOWN:
Log(SEVERIDAD_INFO, TEXT("Unknown"));
break;
case CONNMGR_STATUS_CONNECTED:
Log(SEVERIDAD_INFO, TEXT("Connected."));
break;
case CONNMGR_STATUS_DISCONNECTED:
Log(SEVERIDAD_INFO, TEXT("Disconnected"));
break;
case CONNMGR_STATUS_CONNECTIONFAILED:
Log(SEVERIDAD_INFO, TEXT("Connection has failed and cannot be reestablished"));
break;
case CONNMGR_STATUS_CONNECTIONCANCELED:
Log(SEVERIDAD_INFO, TEXT("User-aborted connection"));
break;
case CONNMGR_STATUS_CONNECTIONDISABLED:
Log(SEVERIDAD_INFO, TEXT("Connection is ready to connect but disabled"));
break;
case CONNMGR_STATUS_NOPATHTODESTINATION:
Log(SEVERIDAD_INFO, TEXT("No path could be found to the destination"));
break;
case CONNMGR_STATUS_WAITINGFORPATH:
Log(SEVERIDAD_INFO, TEXT("Waiting for a path to the destination"));
break;
case CONNMGR_STATUS_WAITINGFORPHONE:
Log(SEVERIDAD_INFO, TEXT("Voice call is in progress"));
break;
case CONNMGR_STATUS_WAITINGCONNECTION:
Log(SEVERIDAD_INFO, TEXT("Attempting to connect"));
break;
case CONNMGR_STATUS_WAITINGFORRESOURCE:
Log(SEVERIDAD_INFO, TEXT("Resource is in use by another connection"));
break;
case CONNMGR_STATUS_WAITINGFORNETWORK:
Log(SEVERIDAD_INFO, TEXT("No path to the destination could be found"));
break;
case CONNMGR_STATUS_WAITINGDISCONNECTION:
Log(SEVERIDAD_INFO, TEXT("Connection is being brought down"));
break;
case CONNMGR_STATUS_WAITINGCONNECTIONABORT:
Log(SEVERIDAD_INFO, TEXT("Aborting connection attempt"));
break;
}
if ((dwStatus == CONNMGR_STATUS_CONNECTIONFAILED) ||
(dwStatus == CONNMGR_STATUS_CONNECTIONCANCELED) ||
(dwStatus == CONNMGR_STATUS_DISCONNECTED)){
if (bDesconectar != TRUE) {
Sleep(10000);
DoMainCommandConnect(hWnd, wMsg, wParam, lParam);
}
else {
bDesconectar = FALSE;
}
}
else {
if (dwStatus == CONNMGR_STATUS_WAITINGFORPHONE) {
// ops llamada telefonica.
// Aqui deberiamos dar por terminada la conexion con el servidor
}
}
return 0;
}
Using connection manager I can now get a gprs connection and perform xmlhttp transfers. While this is in progress the calls to the API function ConnMgrConnectionStatus return CONNMGR_STATUS_CONNECTED. However, if I make a telephone call to the XDA and monitor the ConnMgrConnectionStatus, it returns CONNMGR_STATUS_DISCONNECTED rather than CONNMGR_STATUS_WAITINGFORPHONE which I would have expected. Once the phone call is ended ConnMgrConnectionStatus returns CONNMGR_STATUS_CONNECTED once again.
Any ideas as to what is happening?
Thanks.

Make Option for Today Plugin ?

I made a Today Plugin with option to change the heigh. It run OK when I make option in Today seting. But I want to show option dialog by tap in to my Today Item and change Option from that.
There is the code in WndPro
//Our main WndProc. Does everything after initialization.
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
switch (message)
{
case WM_TIMER:
//Recalculate and paint the time for the count down.
TimeUpdate(hWnd);
return TRUE;
case WM_ERASEBKGND:
//We return true here since we handle our own background painting.
return TRUE;
case WM_TODAYCUSTOM_CLEARCACHE :
//We have no cache to clear so we ignore this message.
break;
case WM_TODAYCUSTOM_QUERYREFRESHCACHE:
//If the cyp member is set to 0 then you must set it to your windows height.
//This makes sure the shell gives you a certain amout of room for your painting.
if (g_bDayView)
{
g_ItemHeight = 26;
}
if (g_bMonthView)
{
g_ItemHeight = 105;
}
if (g_bClockView)
{
g_ItemHeight = 100;
}
//g_curTime = 0;
if (((TODAYLISTITEM*)wParam)->cyp == 0)
{
((TODAYLISTITEM*)wParam)->cyp = g_ItemHeight; //the shell draws a line at the bottom of our window.
return 1;
}
break;
case WM_PAINT:
//Paint like you would in any other application.
hdc = BeginPaint(hWnd, &ps);
PaintAll(hWnd, hdc);
EndPaint(hWnd, &ps);
break;
case WM_LBUTTONUP:
g_stylusPt.x = LOWORD(lParam); g_stylusPt.y = HIWORD(lParam);
if((g_stylusPt.x < 32)&&(g_stylusPt.y < 32))
DialogBox(g_hInstance, (LPCTSTR)IDD_TODAY_CUSTOM, hWnd, (DLGPROC)CustomItemOptionsDlgProc);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
Click to expand...
Click to collapse
And there is the code in Custom Dialog
BOOL WINAPI CustomItemOptionsDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
SHINITDLGINFO shidi;
HWND hCurrentRadioButton;
switch (message)
{
case WM_INITDIALOG:
// Create a Done button and size it.
shidi.dwMask = SHIDIM_FLAGS;
shidi.dwFlags = SHIDIF_DONEBUTTON | SHIDIF_SIPDOWN | SHIDIF_SIZEDLGFULLSCREEN;
shidi.hDlg = hDlg;
SHInitDialog(&shidi);
// select both as the radio button default
if(!g_bUserSet)
{
CheckRadioButton(hDlg, IDC_CLOCK_VIEW, IDC_MONTH_VIEW, IDC_DAY_VIEW);
}
// determine what the current config is and preserve it
else
{
if(g_bDayView)
{
CheckRadioButton(hDlg, IDC_CLOCK_VIEW, IDC_MONTH_VIEW, IDC_DAY_VIEW);
}
if(g_bMonthView)
{
CheckRadioButton(hDlg, IDC_CLOCK_VIEW, IDC_DAY_VIEW, IDC_MONTH_VIEW);
}
if(g_bClockView)
{
CheckRadioButton(hDlg, IDC_DAY_VIEW, IDC_MONTH_VIEW, IDC_CLOCK_VIEW);
}
}
return TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK)
{
// check to see if both is checked
hCurrentRadioButton = GetDlgItem(hDlg, IDC_DAY_VIEW);
if(BST_CHECKED == SendMessage(hCurrentRadioButton, BM_GETCHECK, NULL, NULL))
{
g_bDayView = TRUE;
g_bMonthView = FALSE;
g_bClockView = FALSE;
}
// check to see if only program is checked
hCurrentRadioButton = GetDlgItem(hDlg, IDC_MONTH_VIEW);
if(BST_CHECKED == SendMessage(hCurrentRadioButton, BM_GETCHECK, NULL, NULL))
{
g_bDayView = FALSE;
g_bMonthView = TRUE;
g_bClockView = FALSE;
}
// check to see if only storage is checked
hCurrentRadioButton = GetDlgItem(hDlg, IDC_CLOCK_VIEW);
if(BST_CHECKED == SendMessage(hCurrentRadioButton, BM_GETCHECK, NULL, NULL))
{
g_bDayView = FALSE;
g_bMonthView = FALSE;
g_bClockView = TRUE;
}
g_bUserSet = TRUE;
EndDialog(hDlg, LOWORD(wParam));
return TRUE;
}
break;
}
return FALSE;
}
Click to expand...
Click to collapse
It shows Dialog, change all value of variable. But the Today Item's is not change.
Could anyone tell me how to do.
Thanks
Try this...
Instead of your line:
Code:
if (((TODAYLISTITEM*)wParam)->cyp == 0)
check for cyp not being set to desired height (g_ItemHeight), i.e.:
Code:
if (((TODAYLISTITEM*)wParam)->cyp != g_ItemHeight)
That should work for you.
It works OK
Thank you very, very much
nncuong said:
It works OK
Thank you very, very much
Click to expand...
Click to collapse
My pleasure

WM6 - how to Query WLAN "connection" status

I am desperately trying to work around some unknown problem caused by our NDIS IM driver on WM6 and HTC TyTn ( TyTn at least, but most likely other devices as well ). I started some other threads regarding different facets of this problem, and no help is coming. Now I am just trying to work around it.
in short the problem is when power events happen the WLAN will never connect.
The work around is programmatically open the control panel with STControlPanel class and press the down button 1 time then the f1 key ( right dash ). This "presses connect" on the last configured access point. This works around my problem, however, I need to detect when the access point has connected. There is a "connecting" and "connected" message for the access point in this control panel dialog ( control panel # 17 ).
My Question: Is there some way to get this text "connecting" or "connected" from the control panel #17?
I have tried wzc, ndisuio, winsock, and other "non control panel" ways to detect connected state, but the IM problem fools all these methods. The only thing I have ever seen that successfully shows when the problem has occurred is the "connecting"/"connected" status in the control panel 17.
Please Help Someone.
p.s. If I can get this worked around, we sell a commercial grade ndis intermediate driver toolkit letting you easily write plugins without any of the hard driver details. We have redirectors, transparent proxy, tunnelers, virtual adapters, lots of good stuff. Also the same plugin will work on all windows desktop platforms vista - 98, WM5/6 and CE and also linux and solaris...
Hello skk
What about notification API?
Here is the solution (simple concept) for Your problem. Interesting parts are in bold.
SNapiTest.cpp
Code:
#include "stdafx.h"
#include "SNapiTest.h"
#include <windows.h>
#include <commctrl.h>
#define MAX_LOADSTRING 100
// Global Variables:
HINSTANCE g_hInst; // current instance
HWND g_hWndMenuBar; // menu bar handle
[b]
const DWORD WM_WIFISTATUS = WM_USER + 1;
bool g_connecting;
bool g_connected;
HREGNOTIFY g_hNotify;
HREGNOTIFY g_hNotify2;
[/b]
// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE, LPTSTR);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
MSG msg;
// Perform application initialization:
if (!InitInstance(hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable;
hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_SNAPITEST));
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
// COMMENTS:
//
ATOM MyRegisterClass(HINSTANCE hInstance, LPTSTR szWindowClass)
{
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_SNAPITEST));
wc.hCursor = 0;
wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = 0;
wc.lpszClassName = szWindowClass;
return RegisterClass(&wc);
}
//
// FUNCTION: InitInstance(HINSTANCE, int)
//
// PURPOSE: Saves instance handle and creates main window
//
// COMMENTS:
//
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
TCHAR szTitle[MAX_LOADSTRING]; // title bar text
TCHAR szWindowClass[MAX_LOADSTRING]; // main window class name
g_hInst = hInstance; // Store instance handle in our global variable
// SHInitExtraControls should be called once during your application's initialization to initialize any
// of the device specific controls such as CAPEDIT and SIPPREF.
SHInitExtraControls();
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_SNAPITEST, szWindowClass, MAX_LOADSTRING);
//If it is already running, then focus on the window, and exit
hWnd = FindWindow(szWindowClass, szTitle);
if (hWnd)
{
// set focus to foremost child window
// The "| 0x00000001" is used to bring any owned windows to the foreground and
// activate them.
SetForegroundWindow((HWND)((ULONG) hWnd | 0x00000001));
return 0;
}
if (!MyRegisterClass(hInstance, szWindowClass))
{
return FALSE;
}
hWnd = CreateWindow(szWindowClass, szTitle, WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
// When the main window is created using CW_USEDEFAULT the height of the menubar (if one
// is created is not taken into account). So we resize the window after creating it
// if a menubar is present
if (g_hWndMenuBar)
{
RECT rc;
RECT rcMenuBar;
GetWindowRect(hWnd, &rc);
GetWindowRect(g_hWndMenuBar, &rcMenuBar);
rc.bottom -= (rcMenuBar.bottom - rcMenuBar.top);
MoveWindow(hWnd, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, FALSE);
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
static SHACTIVATEINFO s_sai;
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_HELP_ABOUT:
DialogBox(g_hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, About);
break;
case IDM_OK:
SendMessage (hWnd, WM_CLOSE, 0, 0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_CREATE:
SHMENUBARINFO mbi;
memset(&mbi, 0, sizeof(SHMENUBARINFO));
mbi.cbSize = sizeof(SHMENUBARINFO);
mbi.hwndParent = hWnd;
mbi.nToolBarId = IDR_MENU;
mbi.hInstRes = g_hInst;
if (!SHCreateMenuBar(&mbi))
{
g_hWndMenuBar = NULL;
}
else
{
g_hWndMenuBar = mbi.hwndMB;
}
// Initialize the shell activate info structure
memset(&s_sai, 0, sizeof (s_sai));
s_sai.cbSize = sizeof (s_sai);
[b]
g_connecting = false;
g_connected = false;
{HRESULT hr = RegistryNotifyWindow(SN_WIFISTATECONNECTING_ROOT,
SN_WIFISTATECONNECTING_PATH, SN_WIFISTATECONNECTING_VALUE,
hWnd, WM_WIFISTATUS, 0, NULL, &g_hNotify);}
{HRESULT hr2 = RegistryNotifyWindow(SN_WIFISTATECONNECTING_ROOT,
SN_WIFISTATECONNECTED_PATH, SN_WIFISTATECONNECTED_VALUE,
hWnd, WM_WIFISTATUS, 0, NULL, &g_hNotify2);}
[/b]
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code here...
EndPaint(hWnd, &ps);
break;
[b]
case WM_WIFISTATUS:
{
DWORD newValue = (DWORD) wParam;
WCHAR caption[] = L"Wifi Status";
if ((newValue & SN_WIFISTATECONNECTED_BITMASK) == SN_WIFISTATECONNECTED_BITMASK)
{
if (!g_connected)
{
g_connected = true;
g_connecting = false;
MessageBox(hWnd, L"Connected!!", caption, MB_OK);
}
break;
}
if ((newValue & SN_WIFISTATECONNECTING_BITMASK) == SN_WIFISTATECONNECTING_BITMASK)
{
if (!g_connecting)
{
g_connecting = true;
g_connected =false;
MessageBox(hWnd, L"Connecting...", caption, MB_OK);
}
}
break;
}
[/b]
case WM_DESTROY:
CommandBar_Destroy(g_hWndMenuBar);
[B]
RegistryCloseNotification(g_hNotify);
RegistryCloseNotification(g_hNotify2);
[/B]
PostQuitMessage(0);
break;
case WM_ACTIVATE:
// Notify shell of our activate message
SHHandleWMActivate(hWnd, wParam, lParam, &s_sai, FALSE);
break;
case WM_SETTINGCHANGE:
SHHandleWMSettingChange(hWnd, wParam, lParam, &s_sai);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
{
// Create a Done button and size it.
SHINITDLGINFO shidi;
shidi.dwMask = SHIDIM_FLAGS;
shidi.dwFlags = SHIDIF_DONEBUTTON | SHIDIF_SIPDOWN | SHIDIF_SIZEDLGFULLSCREEN | SHIDIF_EMPTYMENU;
shidi.hDlg = hDlg;
SHInitDialog(&shidi);
}
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK)
{
EndDialog(hDlg, LOWORD(wParam));
return TRUE;
}
break;
case WM_CLOSE:
EndDialog(hDlg, message);
return TRUE;
}
return (INT_PTR)FALSE;
}
Needed includes:
// TODO: reference additional headers your program requires here
#include <snapi.h>
#include <regext.h>
snapi.h
Thank you so much for your post. I just found snapi.h, I assume this is snapitest.h?
IT WORKS!
It works! You are my hero RStein. You are a god among men.
Great. ) Thanks for sharing the results.

[Q] Button MaskFilter?

Hi,
I'm trying to apply a Mask or Blur Filter to some buttons at runtime... This button is reflecting a "layer" object, so I'd like to blur its edges to reflect how transparent is this layer...
I'm able to set a ColorFilter, or apply a maskFIlter to its TextView, but cant figure how to apply a maskFilter to the whole button...
here is the part of my code where I'd like to apply this filter (in a applyFilter method):
Code:
public void createList(LinearLayout lm) {
lm.removeAllViews();
for (int i = 0; i < kwang07Android.nblayers; i++) {
final Button newbtn = new Button(this, null, android.R.attr.buttonStyleSmall);
int col = kwang07Android.layers[i].col;
int newColor = Color.argb(156+(int)(kwang07Android.layers[i].opacite*100), Color.red(col), Color.green(col), Color.blue(col));
newbtn.getBackground().setColorFilter(newColor, MULTIPLY);
[COLOR="DarkOrange"]//applyFilter(newbtn, i, BlurMaskFilter.Blur.INNER);[/COLOR]
newbtn.setText("couche " + Integer.toString(i));
newbtn.setId(i);
newbtn.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,30+kwang07Android.layers[i].thickness/20));
final int finalI = i;
newbtn.setOnTouchListener(new Button.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
showColorPickerDialogDemo(newbtn, finalI);
}
return false;
}
});
lm.addView(newbtn);
}
...
Any advice?
Thanks.

How to draw or erase on a photo loaded onto a Imageview?

As what was stated on the header I want to implement either a "paint" function for user to edit paint/censor unwanted parts of a photo displayed on a imageview before uploading it to a server in the edited format and a redo function if user makes a mistake while editing?
How do I come about doing it, I've read relevant topics on Canvas, or FingerPaint but still puzzled on how to implement it based on my project here? Tried referencing to the links here and here but without success in implementing the codes into my project code due to my lack of programming skills.
Thanks for any help rendered!
Tried integrating the codes below into my code above (image preview after taking a photo with the camera) for user to start editing via painting but still not working? Thanks for any help rendered!
Code:
public class Drawing extends View {
private Paint mPaint, mBitmapPaint;
Intent intent = getIntent();
Bitmap mBitmap = (Bitmap) intent.getParcelableExtra("BitmapImage");
private Canvas mCanvas;
private Path mPath;
private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;
private int color, size, state;
private ArrayList<Path> paths = new ArrayList<Path>();
private ArrayList<Path> undonePaths = new ArrayList<Path>();
private ArrayList<Integer> colors = new ArrayList<Integer>();
private ArrayList<Integer> sizes = new ArrayList<Integer>();
public Drawing(Context c) {
super(c);
}
public Drawing(Context c,int width, int height, int size, int color, int state) {
super(c);
mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
mPath = new Path();
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
// mBitmapPaint = new Paint(Paint.DITHER_FLAG);
// mBitmapPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
setColor(color);
setSize(size);
setState(state);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
}
@Override
protected void onDraw(Canvas canvas) {
// canvas.drawColor(Color.TRANSPARENT);
// canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
//
// if (state == 0)
// mBitmap.eraseColor(Color.TRANSPARENT);
for (int i = 0; i < paths.size(); i++) {
mPaint.setColor(colors.get(i));
mPaint.setStrokeWidth(sizes.get(i));
canvas.drawPath(paths.get(i), mPaint);
}
mPaint.setColor(color);
mPaint.setStrokeWidth(size);
canvas.drawPath(mPath, mPaint);
}
public void setColor(int color) {
this.color = color;
}
public void setSize(int size) {
this.size = size;
}
public void setState(int state) {
this.state = state;
// if (state == 0)
// mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
// else
// mPaint.setXfermode(null);
}
public void onClickUndo() {
if (paths.size() > 0) {
undonePaths.add(paths.remove(paths.size() - 1));
sizes.remove(sizes.size() - 1);
colors.remove(colors.size() - 1);
invalidate();
}
}
private void touch_start(float x, float y) {
undonePaths.clear();
mPath.reset();
mPath.moveTo(x, y);
mX = x;
mY = y;
}
private void touch_move(float x, float y) {
float dx = Math.abs(x - mX);
float dy = Math.abs(y - mY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
mX = x;
mY = y;
}
}
private void touch_up() {
mPath.lineTo(mX, mY);
mCanvas.drawPath(mPath, mPaint);
colors.add(color);
sizes.add(size);
paths.add(mPath);
mPath = new Path();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touch_start(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
touch_move(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP:
touch_up();
invalidate();
break;
}
return true;
}
}

Categories

Resources