CameraCaptureDialog in VS2005/CF2 - Windows Mobile Development and Hacking General

Has anyone used the CameraCaptureDialog successfully on a PDA with camera to capture an image to a file?
I tried the following code on my O2 Atom (a camera-equipped PDA phone running Windows Mobile 5.0 & CF2) but all I get is a static image in the dialog. After clicking OK in the dialog, nothing happens. The image is not saved, which should not be the case. Doing a trace in debug mode shows that the FileName property is an empty string immediately after the ShowDialog() call.
CameraCaptureDialog c = new CameraCaptureDialog();
c.DefaultFileName = "test.jpg";
c.InitialDirectory = @"\My Documents";
c.ShowDialog();
(I've posted a similar to another thread. Hope it's ok to start a new thread.)

I have used successfullly with my Qtek 9100 (htc wizard).
But it annoys me that I have to click the releasebutton in the cameradialog to retrieve the picture. I would really like to capture a picture directly from .net CF
Andreas

andemann said:
But it annoys me that I have to click the releasebutton in the cameradialog to retrieve the picture. I would really like to capture a picture directly from .net CF
Click to expand...
Click to collapse
Hi Andreas, for my case, I don't see any button in the dialog, but the left softkey is Cancel and the right softkey is Menu (for adjusting properties like brightness and quality). And at the top-right is the OK. I assume that clicking OK captures the picture and saves it as a file (for my case, it doesn't).
Could you tell me more about the releasebutton? And doesn't the CameraCaptureDialog save a file to the ROM after snapping the picture?
Thanks for the reply!

On my device I have a dedicated camerabutton, when I press this button, the picture is captured and the cameradialog asks me if I want to save the picture and return to the application or delete it (take another)
Andreas

Well I guess I'll move on to see if it can be done with unmanaged code. I had wanted to use a camera api that works on all WM5 devices. Since there's the CameraCaptureDialog class for managed code, I assume it's definitely doable with low level code.
Does anyone know where's a good place to start searching for info?

methods
I try to do the same on an Universal
I find an interesting thread on http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=253920&SiteID=1 but I can't achieve realize it.
I try that method and I find that loading the CameraDialog open two windows who's classnames are "WCE_IA_Camera_Main" (and a subwindow "WCE_IA_Camera_Skin") and "IACW_AGENT". I try the method exlained on the thread for each window but this didn't make the trick.
I create a thread who is launched before calling the cameraDialog and in this thread, I send message press enter to the camera handle window (I hope) : SendMessage(hCamWnd, WM_KEYDOWN, VK_ENTER, NULL)
I didn't work. Any tips ?
PS: there is a method with directShow who is much more difficult

I have the same issue about the FileName. The string is empty just after the CameraCaptureDialog is openned.
but here is the method i used to take automatic captures:
I started a timer just after the dialog is openned and simulated the message sent by the capture button on my PDA... first u need the message number and the parameters it is used... here is how to get it..
1. open Remote spy from visual studio remote tools in all programs.
2. Connect to your Smartphone or PDA.
3. open the camera and from Remote spy.. click on Target>> Refresh.
4. check the windows list and you will find a camera window. choose it and from spy menu click messages.
5. now remote spy will show you all messages that is sent to the camera dialog, so it's time to press the capture button or equivalent from your smartphone or PDA. and after you press it close the camera dialog.
6. in the messages window check for the message sent when you pressed the capture button. take the message value, wparam, and LParam. *you might get two messages for the same button press. like key_Up and key_Down. mine worked with the key_Up. you might need to do some tries to find the right message neway*
now you have everything you need to simulate the capture key.
in ur code u will need to import both GetForeGroundWindow and SendMessage functions from CoreDll. and after openning the camera dialog enable a time to make sure the cameraDialog is openned and worked fine and then when the time ticks get the CameraDialog window handle using GetForeGroundWindow and the send the capture button message to it using SendMessage.
here is my full code.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Microsoft.WindowsMobile.Forms;
using System.Runtime.InteropServices;
using Microsoft.WindowsMobile.PocketOutlook;
using Microsoft.WindowsMobile.Status;
namespace CamCapture
{
unsafe public partial class Form1 : Form
{
[DllImport("CoreDll")]
public static extern IntPtr FindWindow(
string lpClassName, // class name
string lpWindowName // window name
);
[DllImport("CoreDll")]
public static extern IntPtr SendMessage(
IntPtr hWnd, // handle to destination window
uint Msg, // message
uint wParam, // first message parameter
uint lParam // second message parameter
);
[DllImport("CoreDll")]
public static extern IntPtr GetForegroundWindow();
public Form1()
{
InitializeComponent();
}
private void menuItem2_Click(object sender, EventArgs e)
{
Application.Exit();
}
private void menuItem1_Click(object sender, EventArgs e)
{
CameraCaptureDialog ccd = new CameraCaptureDialog();
ccd.Owner = this;
ccd.Mode = CameraCaptureMode.Still;
ccd.InitialDirectory = @"\My Documents\My Pictures";
ccd.DefaultFileName = @"test.jpeg";
ccd.Resolution = new Size(1600, 1280);
ccd.StillQuality = CameraCaptureStillQuality.High;
if (ccd.ShowDialog() == DialogResult.OK)
{
timer1.Enabled = true;
}
Show();
ccd.Dispose();
}
private void timer1_Tick(object sender, EventArgs e)
{
IntPtr hwnd = GetForegroundWindow();
SendMessage((IntPtr)hwnd, 0x201, 0x1, 0x10000D);
timer1.Enabled = false;
}
}
}

i took 10 pictures and i cant recognize who is the press button event
{
"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"
}
furthermore text format is last example is very different from: SendMessage((IntPtr)hwnd, 0x201, 0x1, 0x10000D);
thanks

you will need to watch the remote spy for a while without clicking the button so you recognise the normal messages that is always sent by the camera. And after that you can click the capture button and you will notice a different message on the messages window. The only way you know it is by watching the remote spy window for a while, then try and error.

I let him 1 minute without move it and close it and the messages are the same. next other minute and took 5 pictures consecutives without move camera and same result
Exist a solution in mortscript, bit i need take picture while send bluetooth messages and script language dont let do both things at the same time (sorry for my bad english)
if question "Please set the Camera app to photo mode before executing this script. Additionally, please remember to disable <<Reviev After Capture>> option in Camera before running this script! Run the script?","Important note"
setbacklight 1,1
Input limit, 1, "Total images to capture","MultiCapture"
if equals "",%limit%
set limit,10
endif
set total,0
Input delayer, 1, "Capture interval (seconds)","MultiCapture"
set delayer,%delayer%*1000
if equals %delayer%,0
set delayer,1000
endif
%czas%=%delayer%*%limit%/1000
%czas_m%=%czas%/60
%czas%="Total capture time: "&%czas%&" seconds, this is "&%czas_m%&" minutes."
message %czas%,"MultiCapture"
if question "Lock the touchscreen?","Touchscreen lock"
run tpdisable.exe
endif
run camera.exe
WaitForActive "Camera",10
setbacklight 0,0
while wndActive "Camera"
SendCR "Camera"
sleep %delayer%
%total%=%total%+1
if equals %total%,%limit%
Close "Camera"
endif
endwhile
run tpenable.exe
%total%="Images captured: " & %total%
message %total%,"Done"
endif
Click to expand...
Click to collapse
thanks for answer

Related

clipboard problem

I have been writing a small tool for someone that has no windows and finishes after it dose its thing. I try to place the results on the clipboard as text in both formats (CF_TEXT & CF_UNICODETEXT). I use localalloc to get the memory I need, and I do not free it, the next program to call EmptyClipboard() will do that.
When my program runs under normal operation it flushes whatever is on the clipboard (tested it works) but then the text is gone. I can't paste to pword. If I make the process wait for a while using sleep() before ending, then go to pword, I can paste. When the program finaly finishes I can no longer get the text from the clipboard.
What is happening to the text? If the memory was being freed I would still expect to get some random garbage when I paste, but I get nothing. No other program is flushing the clipboard in that time, I have already closed my use of it and tested. Other programs have plenty of oportunity to flush the clipboard while I happily paste in that sleep period (I tested changing to different programs in that period with no ill effect).
I have tried obtaining the memory using globalalloc localalloc new malloc.
All work identically.
lookie here....
BOOL sendToClipboard(CString data)
{
BOOL result=TRUE;
if (OpenClipboard(NULL))//pass NULL for no window
{
HGLOBAL hGmem1,hGmem2;
HANDLE res;
char* pGmem1;
ushort* pGmem2;
CString ushorText=data;
char *charText=(char*)malloc(data.GetLength()+1);
memset(charText,'\0',data.GetLength()+1);
//convert from input
for(int i=0;i<data.GetLength();i++)
{
char con='\0';
VarI1FromUI2(data.GetAt(i),&con);
*(charText+i)=con;
}
if(EmptyClipboard()==0)//get ownership
{
result=FALSE;
}
//when moveable returns a object, fixe a pointer
hGmem1=GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE,(ushorText.GetLength()+1));
hGmem2=GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE,(ushorText.GetLength()+1)*sizeof(ushort));
//get pointer to memory
pGmem1=(char*)GlobalLock(hGmem1);
pGmem2=(ushort*)GlobalLock(hGmem2);
if (pGmem1&&pGmem2)
{
// UNICODE to clipboard
memcpy(pGmem2,ushorText.GetBuffer(0),(ushorText.GetLength()+1)*2);
res=SetClipboardData(CF_UNICODETEXT,hGmem2);
if(res==NULL)
{
result=FALSE;
}
// ASCII to clipboard
strcpy((char*)pGmem1,charText);
res=SetClipboardData(CF_TEXT,hGmem1);
if(res==NULL)
{
result=FALSE;
}
}
//clean up but don't free, next clipboard user dose that
pGmem1=NULL;
pGmem2=NULL;
if(charText)
{
free(charText);
charText=NULL;
}
GlobalUnlock(hGmem1);
GlobalUnlock(hGmem2);
CloseClipboard();
}
else
{
result=FALSE;
}
//Sleep(10000);
return result;
}
That code will put the desired text on the clipboard and it will stay there on wm2003 devices and above. On 2002 it puts it there only as long as the process is going, regardless of what windows I create etc. To see for your self uncomment the sleep it works, comment it out it fails.
I know there is a solution because I use a little program called PocketNotepad that has persistant clipboard data after its process has stopped.

[HELP] Creating a simple app

Hi guys!
I want to create a simple app, i have tried to, but i fail every time (in the very start!)
It shall be built in this way:
When opened a list will appear. When an element is chosen another list will appear.
In the second list, when an item is selected text will appear!
Can some very nice chap help me?
What have you tried so far? Are you developing in eclipse and java? Maybe try the Google App Inventor first.
You are basically wanting an app with a bunch of listviews (class extends listview activity) and finally a standard activity with a textview.
That should be pretty simple but then you have to populate the lists with some kind of data.
The best way to start learning is to just start, and keep at it. Google is your friend, every question you have, google it. There is a ton of resources on the net for android already. Chances are your question has been asked by someone else.
If you are wanting someone to do it all for you...good luck. Unless you pay someone to do it.
I have builded my own j2me midlet with microemulator, looks good, but i can't enter any element in any listview. Guess it is because one could not use the center key in the midlet but had to use the to other keys. You know, just below the screen on good old phones.
You're putting a lot into a "simple" app in my opinion; especially if you're new to programming.
Restart a new project. Create an array of data. Create array list and loop through your data array and add the items to the array list. Create an array adapter that will get populated with your list. Setup main.xml with <ListView> tag.
If you get that far, your list should be displayed. Then work on your onClicks'. It's going to get confusing if you're going to have a clickable listview come up that's clickable and does something else. Why not just one list?
Sounds very hard :S how about creating a kind of book with chapters, so one can start up the app and choose a chapter and be sent directly to it? Alternative for the lists.
Well, you have to deal with "onClicks" no matter whether they are buttons or items in a listview.
Here's a little code to help you out with a listview:
Code:
// Create some data
String myArray[] = {"Chapter 1", "Chapter 2", "Chapter 3"};
// Create a list to hold our data
ArrayList<String> myList = new ArrayList<String>();
// Load the list; usually done from an array in a loop
for(int i=0; i<myArray.length(); i++) {
myList.add(myArray[i]);
}
// Setup Array Adapter with myList
ArrayAdapter<String> aa = new ArrayAdapter<String>(this, android.R.layout.test_list_item, myList);
// Get id of ListView in xml file
lv = (ListView) findViewById(R.id.myListView);
// And display it
lv.setAdapter(aa);
Typed that off top of my head so I might not be 100%; compiler will let you know LOL Once you get a list displayed, Google something like "Android ListView onClick" for further help.
This code is pretty basic; if you don't understand it, you may want to look into some tutorials on Android programming.
Good luck
Rootstonian said:
Well, you have to deal with "onClicks" no matter whether they are buttons or items in a listview.
Here's a little code to help you out with a listview:
Code:
// Create some data
String myArray[] = {"Chapter 1", "Chapter 2", "Chapter 3"};
// Create a list to hold our data
ArrayList<String> myList = new ArrayList<String>();
// Load the list; usually done from an array in a loop
for(int i=0; i<myArray.length(); i++) {
myList.add(myArray[i]);
}
// Setup Array Adapter with myList
ArrayAdapter<String> aa = new ArrayAdapter<String>(this, android.R.layout.test_list_item, myList);
// Get id of ListView in xml file
lv = (ListView) findViewById(R.id.myListView);
// And display it
lv.setAdapter(aa);
Typed that off top of my head so I might not be 100%; compiler will let you know LOL Once you get a list displayed, Google something like "Android ListView onClick" for further help.
This code is pretty basic; if you don't understand it, you may want to look into some tutorials on Android programming.
Good luck
Click to expand...
Click to collapse
Dont forget your setcontentview()
I said "off the top of my head" LOL
I usually don't provide code, but I was in a good mood. There is still plenty of work to be done around that snippet I posted...as you well know
#¤&*@ 1 buck for the man who will write the 'skeleton' of this app!
Ihaveatattoo said:
#¤&*@ 1 buck for the man who will write the 'skeleton' of this app!
Click to expand...
Click to collapse
why are you asking for a how to if you are not willing to put any effort in it ?
i dont get it ...
It's about two months ago i asked for help. I the meantime i have tried to make it. But thanks, i just remembered i had some code to work from!
The problem is, i can almost no java. And i have another study and work.
At least post the code you have so far. You are asking for help with an app you have barely described with code we have never seen.
Added my code snippet to empty project, added listview to main.xml. Took me longer to remember my photobucket password! LOL
Now, if you're not a programmer, there isn't much we can do to help besides writing it for you. And we like to get paid for that
{
"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"
}
I know how to make that.. ;-) Problem now is to make the items in menu "click able ". I'LLC post my code soon.
Thanks for help chaps!

Align 2 texts, 1 normal, 1 opposite

I make a android application with a button where in there a total of 4 texts and I want to align the first 2. One at the most left side of the bottom text and the other and the right side of the bottom text.
So from 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"
}
Code:
setText(item.title + " " + item.roomId + "\n" + item.teacher + " " + item.classes);
To this:
This is my class where I extend Button:
Code:
/**
* Custom view that represents a {@link ScheduleItem} instance, including its
* title and time span that it occupies. Usually organized automatically by
* {@link ScheduleItemsLayout} to match up against a {@link TimeRulerView}
* instance.
*/
public class ScheduleItemView extends Button {
private ScheduleItem mItem;
public ScheduleItemView(Context context, ScheduleItem item) {
super(context);
mItem = item;
setSingleLine(false);
setText(item.title + " " + item.roomId + "\n" + item.teacher + " "
+ item.classes);
// TODO: turn into color state list with layers?
int textColor = Color.WHITE;
int accentColor = item.accentColor;
LayerDrawable buttonDrawable = (LayerDrawable) context.getResources()
.getDrawable(R.drawable.btn_block);
buttonDrawable.getDrawable(0).setColorFilter(accentColor,
PorterDuff.Mode.SRC_ATOP);
buttonDrawable.getDrawable(1).setAlpha(item.containsStarred ? 255 : 0);
setTextColor(textColor);
setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources()
.getDimensionPixelSize(R.dimen.text_size_small));
setGravity(Gravity.CENTER | Gravity.BOTTOM);
setBackgroundDrawable(buttonDrawable);
}
public ScheduleItem getScheduleItem() {
return mItem;
}
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
measure(MeasureSpec.makeMeasureSpec(getMeasuredWidth(),
MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(
getMeasuredHeight(), MeasureSpec.EXACTLY));
// layout(getLeft(), getTop(), getRight(), getBottom());
setGravity(Gravity.CENTER);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(getRight() - getLeft(), getBottom() - getTop());
}
}
What I've tried is instead of extending Button, extending RelativeLayout:
Code:
/**
* Custom view that represents a {@link ScheduleItem} instance, including its
* title and time span that it occupies. Usually organized automatically by
* {@link ScheduleItemsLayout} to match up against a {@link TimeRulerView}
* instance.
*/
public class ScheduleItemView extends RelativeLayout {
private ScheduleItem mItem;
public ScheduleItemView(Context context, ScheduleItem item) {
super(context);
mItem = item;
// TODO: turn into color state list with layers?
int textColor = Color.WHITE;
int accentColor = item.accentColor;
LayerDrawable buttonDrawable = (LayerDrawable) context.getResources()
.getDrawable(R.drawable.btn_block);
buttonDrawable.getDrawable(0).setColorFilter(accentColor,
PorterDuff.Mode.SRC_ATOP);
buttonDrawable.getDrawable(1).setAlpha(item.containsStarred ? 255 : 0);
// Three TextViews to hold the `title`, `roomId`
// and `teacher&room` independently
TextView tvTitle = new TextView(context);
TextView tvRoomId = new TextView(context);
TextView tvTeacherAndClasses = new TextView(context);
// Example ids
tvTitle.setId(100);
tvRoomId.setId(101);
tvTeacherAndClasses.setId(102);
tvTitle.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources()
.getDimensionPixelSize(R.dimen.text_size_small));
tvRoomId.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources()
.getDimensionPixelSize(R.dimen.text_size_small));
tvTeacherAndClasses.setTextSize(TypedValue.COMPLEX_UNIT_PX,
getResources().getDimensionPixelSize(R.dimen.text_size_small));
tvTitle.setPadding(30, 20, 30, 0);
tvRoomId.setPadding(30, 20, 30, 0);
tvTeacherAndClasses.setPadding(30, 5, 30, 20);
tvTitle.setTextColor(textColor);
tvRoomId.setTextColor(textColor);
tvTeacherAndClasses.setTextColor(textColor);
// Set text
tvTitle.setText(item.title);
tvRoomId.setText(item.roomId);
tvTeacherAndClasses.setText(item.teacher + " " + item.classes);
// LayoutParms
RelativeLayout.LayoutParams paramsTitle = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
paramsTitle.addRule(RelativeLayout.ALIGN_LEFT,
tvTeacherAndClasses.getId());
RelativeLayout.LayoutParams paramsRoomId = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
paramsRoomId.addRule(RelativeLayout.ALIGN_RIGHT,
tvTeacherAndClasses.getId());
RelativeLayout.LayoutParams paramsTeacherAndClasses = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
paramsTeacherAndClasses.addRule(RelativeLayout.CENTER_HORIZONTAL);
paramsTeacherAndClasses.addRule(RelativeLayout.BELOW, tvTitle.getId());
// Add Views to this RelativeLayout
addView(tvTitle, paramsTitle);
addView(tvRoomId, paramsRoomId);
addView(tvTeacherAndClasses, paramsTeacherAndClasses);
// setGravity(Gravity.CENTER | Gravity.BOTTOM);
// Set the background as LayerDrawable
setBackgroundDrawable(buttonDrawable);
}
public ScheduleItem getScheduleItem() {
return mItem;
}
But then only the LayerDrawable is displaying, the text is not displaying. What I've done wrong? I hope that someone can help me with this, the guys on StackOverflow have point me in a good direction with the above code but it's still not working.
The source of the project can be downloaded here (which you can import in Eclipse):
http://we.tl/5PnmaZKXvL
RelativeLayout should be a good idea!
Have you debuged the app? What is the text of the TextViews? The text-size? Why do you set the ids for the TextViews?
Regards
EmptinessFiller said:
RelativeLayout should be a good idea!
Have you debuged the app? What is the text of the TextViews? The text-size? Why do you set the ids for the TextViews?
Regards
Click to expand...
Click to collapse
I've debugged the app, this is what I've tried:
Log the id's of tvTitle, tvRoomId, and tvTeacherAndClasses with getId() to see if the id's is set. (The id's are set in order to get the addRule working)
I've tried to comment these lines:
tvTitle.setId(100);
tvRoomId.setId(101);
tvTeacherAndClasses.setId(102);
And the following as well:
paramsTitle.addRule(RelativeLayout.ALIGN_LEFT, tvTeacherAndClasses.getId());
paramsRoomId.addRule(RelativeLayout.ALIGN_RIGHT, tvTeacherAndClasses.getId());
paramsTeacherAndClasses.addRule(RelativeLayout.BELOW, tvTitle.getId());
If the ids were the problem, the text should show, but the three textviews would overlap now. But I still see no text.
I've tried to give the TextView a color with tvTitle.setBackgroundColor(Color.GREEN); but I still see no text neither a color.
I've tried to comment out setBackgroundDrawable(buttonDrawable); to see if the text's show up. But then I see no text and no button.
I've also tried to use bringToFront() but neither the text is not showing
As last I've tried to use a concrete value for the TextSize with tvTitle.setTextSize(25) but the text is unfortunately not showing.
What could be the problems:
I use Android-ViewPagerIndicator and ViewPager this could be a problem. (Maybe with restoring the view state or multiple id's).
I've only switched a Button to RelativeLayout, I really don't see why problems being introduced in that transition. Does someone know what could be the problem?
Anyone? I've updated the post with a new download link.
You could call getPaint on the button instance and with measuretext you could get the size of the spaces to calculate the count of spaces for the specific size of the button
Just an idea, no idea how it will work in practice
Tapatalked...

[GUIDE] Customize Lollipop's official Clock application

{
"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"
}
I am a person who needs many many multiple alarms to wake up early in the morning.
Every clock/alarm applications I tried has no feature that turning on or off all alarms at once.
So I decided to customize google's official android clock app.
Let's get it started.
### Needed #####
google's clock app source (I use Lollipop's source for my device)
buttons icon image
### Steps #####
1) download source from googlesource.com repository
android system clock application's package name is "DeskClock".
You can clone the source like below
Code:
git clone -b lollipop-release https://android.googlesource.com/platform/packages/apps/DeskClock
2. import it & remove errors
When you import the project to your IDE, you will get thousand of import errors.
Check below
SDK Version
- Make sure that you have lollipop sdk and check "Build Target" in "Project Properties"
AndroidManifest
- Specify min/targetSdkVersion, if it is not in AndroidManifest.xml
- There is "DEVICE_POWER" permission because it is android system app but we can't build system application so just remove it. (In my usage, it seems to be no problem)
Library
- Put android support-library jar file and add it to project build path.
3. Add button icons
- add ic_all_on.png, ic_all_off.png as drawable
4. Edit the sources
There is "DeskClockFragmet" class which is parent of alam/timer/stopwatch/clock's Fragment class.
It uses common layout "desk_clock.xml". It has three buttons (Fab, sub buttons) in the bottom of the screen and Alarm Fragment does not use and just hide sub buttons.
Which means we can easily add buttons to that place.
setLeftRightButtonAppearance() in AlarmClockFragment.java
Code:
@Override
public void setLeftRightButtonAppearance() {
final DeskClock activity = (DeskClock) getActivity();
if (mLeftButton == null || mRightButton == null ||
activity.getSelectedTab() != DeskClock.ALARM_TAB_INDEX) {
return;
}
[COLOR="SeaGreen"] // mLeftButton.setVisibility(View.INVISIBLE);
//mRightButton.setVisibility(View.INVISIBLE);
mLeftButton.setEnabled(true);
mRightButton.setEnabled(true);
mLeftButton.setVisibility(View.VISIBLE);
mRightButton.setVisibility(View.VISIBLE);
mLeftButton.setImageResource(R.drawable.ic_all_off);
mRightButton.setImageResource(R.drawable.ic_all_on);[/COLOR]
}
set mLeft/RightButton enabled and change visibilty to VISIBLE, set button image as drawable we added.
Override onLeftButtonClick/onRightButtonClick() from parent (DeskClockFragment.class) and call switchAlarms() what we will implement.
Code:
@Override
public void onLeftButtonClick(View view) {
super.onLeftButtonClick(view);
mAdapter.switchAlarms(false);
Toast.makeText(getActivity(), "Every Alarms Disabled!!", Toast.LENGTH_SHORT).show();
}
@Override
public void onRightButtonClick(View view) {
super.onRightButtonClick(view);
mAdapter.switchAlarms(true);
Toast.makeText(getActivity(), "Every Alarms Enabled!!", Toast.LENGTH_SHORT).show();
}
+ I just hide menu button in bottom-right just in alarm tab because right and menu button are overlayed.
onCreateView() in AlarmClockFragment.java
Code:
if (menuButton != null) {
// if (isLandscape) {
// menuButton.setVisibility(View.GONE);
// } else {
// menuButton.setVisibility(View.VISIBLE);
// setupFakeOverflowMenuButton(menuButton);
// }
//remove menu button
menuButton.setVisibility(View.GONE);
}
There is AlarmItemAdapter sub class in AlarmClockFragment.java which extends CursorAdapter.
We have to implement something that change actual alarm data in inner database and change views depend on each alarm's on/off value.
I just added a method "swichAlarms" into this sub class to do that.
boolean enabled value is passed as parameter (on : true / off : false)
Get every alarm's view and change the view when the alarm on/off status has to be changed
Also there's a way to get alarms llist in Alarm.java that is getAlarms() method.
I use it to get alarms list a alarm's enabled value is different.
And change alarms enabled value with asyncUpdateAlarm() method in AlarmClockFragment.java
That's all!
easy?
Code:
// added by donghe
/**
* A convenience method to enable or disable every alarm.
* Get child view (visible view) in alarm list and changing ItemAlpha whether if its enabled value is different
* Get alarm(s) linked list from Alarms Class only if the alarm has to be updated.
* Do asynchronous updating.
* @param enabled true for turning on, false for turning off
*/
private void switchAlarms(boolean enabled) {
int totalLength = mList.getCount();
for (int i = 0; i < totalLength; i++) {
View v = mList.getChildAt(i);
if (v != null) {
ItemHolder h = (ItemHolder)(v.getTag());
if (h != null && h.alarm.enabled != enabled) {
setDigitalTimeAlpha(h, enabled);
}
}
}
String selection = null;
if(enabled){
selection = "ENABLED = 0";
}
else{
selection = "ENABLED = 1";
}
ContentResolver cr = getActivity().getApplicationContext().getContentResolver();
List<Alarm> alarmList = Alarm.getAlarms(cr, selection, null);
for(Alarm alarm: alarmList){
alarm.enabled = enabled;
asyncUpdateAlarm(alarm, false);
}
}
Now I feel comfortable to sleep lately in the evening and wake up early in the morning
Hope this thread is helpful to someone like me.
I attached project archive and apk.
Enjoy it!
Thanks men!

[Tutorial][APP] PinP Shortcuts | How to Implement Picture in Picture Mode [API 26+]

{
"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"
}
Picture in Picture Mode (PinP) introduced on Android 8 (API 26) for All Android devices.
Its most used functionality is to shoa w preview of some data like Video Players, Maps & etc.
But there is also an option to add Custom Action & with this, you can do whatever you want to do.
This is Tutorial is about How to Add PinP for an Activity & Implementing Custom Actions to Create Shortcuts of Other Apps & Open Them
Click to expand...
Click to collapse
# Let Start #​
What do you need to get started...
- Know How to Create Hello World Project
- Basic Info about Android Apps Files (.Java, .xml)/Components (Activity, Service)
Click to expand...
Click to collapse
What will you learn...
- Configure an Activity for PinP Mode
- Create PendingIntent
- Load Apps Info from PackageManager (AppName, AdaptiveIcons & etc)
- Load File Data in Lines
Click to expand...
Click to collapse
- Create new Android Studio Project, then open AndroidManifest.xml to add PinP attributes.
(I suggest to create specific Activity to handle PinP)
Code:
<activity
android:name=".PictureInPicture.PinP"
android:label="@string/title_activity_pin_p"
[B][COLOR="Blue"]android:resizeableActivity="true"
android:supportsPictureInPicture="true"[/COLOR][/B]
android:theme="@android:style/Theme.DeviceDefault.Wallpaper.NoTitleBar" />
<!-- I used Wallpaper theme cause in my case I want to have transparent background that shows home launcher wallpaper -->
- Now Open your PinP Activity, PinP.java
The layout your design for this activity will show inside PinP Window.
(Here I set 3 ImageViews to load icons of selected apps that I load from a saved file)
To enter PinP Mode your need only to call this activity.enterPictureInPictureMode(); But you should add some functionality to it. READ COMMENTS IN CODE
Code:
public void enterPinP(){
[COLOR="Red"]//load packageNames from saved file[/COLOR]
List<String> appShortcutsPackageName = Arrays.asList(functionsClass.readFileLine(".autoSuper"));
[COLOR="red"]//set icon of apps to imageView[/COLOR]
imageViewOne.setImageBitmap(appIconBitmap(appShortcutsPackageName.get(0)));
imageViewTwo.setImageBitmap(appIconBitmap(appShortcutsPackageName.get(1)));
imageViewThree.setImageBitmap(appIconBitmap(appShortcutsPackageName.get(2)));
[COLOR="red"]//get main intent of apps[/COLOR]
Intent intentOne = getPackageManager().getLaunchIntentForPackage(appShortcutsPackageName.get(0)).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Intent intentTwo = getPackageManager().getLaunchIntentForPackage(appShortcutsPackageName.get(1)).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Intent intentThree = getPackageManager().getLaunchIntentForPackage(appShortcutsPackageName.get(2)).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
[COLOR="red"]//create pending intent for actions on PinP Window [/COLOR]
[COLOR="red"]//you can also [b]getService()[/b] & [b]getBroadcast()[/b] [/COLOR]
final PendingIntent pendingIntentOne = PendingIntent.getActivity(getApplicationContext(), 333, intentOne,0);
final PendingIntent pendingIntentTwo = PendingIntent.getActivity(getApplicationContext(), 666, intentTwo,0);
final PendingIntent pendingIntentThree = PendingIntent.getActivity(getApplicationContext(), 999, intentThree,0);
[COLOR="red"]//here I add icon from resource to indicate where to click on PinP Window[/COLOR]
final Icon oneIcon = Icon.createWithResource(getApplicationContext(), R.drawable.ic_click);
final Icon twoIcon = Icon.createWithResource(getApplicationContext(), R.drawable.ic_click);
final Icon threeIcon = Icon.createWithResource(getApplicationContext(), R.drawable.ic_click);
[COLOR="red"]//remote actions to handle click from PinP Window[/COLOR]
final ArrayList<RemoteAction> remoteActions = new ArrayList<>();
remoteActions.add(new RemoteAction(oneIcon, appName(appShortcutsPackageName.get(0)), appName(appShortcutsPackageName.get(0)), pendingIntentOne));
remoteActions.add(new RemoteAction(twoIcon, appName(appShortcutsPackageName.get(1)), appName(appShortcutsPackageName.get(1)), pendingIntentTwo));
remoteActions.add(new RemoteAction(threeIcon, appName(appShortcutsPackageName.get(2)), appName(appShortcutsPackageName.get(2)), pendingIntentThree));
//
final PictureInPictureParams.Builder pictureInPictureParamsBuilder = new PictureInPictureParams.Builder();
pictureInPictureParamsBuilder.setActions(remoteActions);
pictureInPictureParamsBuilder.setAspectRatio(new Rational(50, 100));
PictureInPictureParams pictureInPictureParams = pictureInPictureParamsBuilder.build();
[B][COLOR="red"]//This is Main Functions. That you can Call from any Activity [/COLOR]
[COLOR="RoyalBlue"]enterPictureInPictureMode(pictureInPictureParams);[/COLOR][/B]
}
So wherever you call this function, it will enter to Picture in Picture Mode.
For Example, when click a button or @onPause() to continue showing some data.
I call it from onCreate(Bundle bundle) cause I create an activity specific for PinP Mode.
Also, you can recognize whenever your activity enter full screen mode Or PinP by overriding this functions
It is good way to add/remove views If you are using same activity for both full screen and PinP mode.
Code:
@Override
public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode, Configuration configuration) {
super.onPictureInPictureModeChanged(isInPictureInPictureMode, configuration);
if (isInPictureInPictureMode){
//picture in picture mode
}
else {
//full screen mode
}
}
Note: Limited amount of RemoteActions can be set for PinP Mode that you can get it from activity.getMaxNumPictureInPictureActions();
Oo. Download | PinP Shortcuts .oO
Super Shortcuts | Available in Beta Stage
Feel Free to Ask for Promo Code
Thanks for Support my Projects​Don't forget to Hit Thanks​
PinP Shortcuts | Extra Functions
Extra Functions Used in Tutorial​
Code:
public Bitmap [B]appIconBitmap[/B](String pack){
Bitmap bitmap = null;
try{
Drawable drawableIcon = context.getPackageManager().getApplicationIcon(pack);
if (drawableIcon instanceof BitmapDrawable) {
bitmap = ((BitmapDrawable)drawableIcon).getBitmap();
}
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (drawableIcon instanceof AdaptiveIconDrawable){
Drawable backgroundDrawable = ((AdaptiveIconDrawable) drawableIcon).getBackground();
Drawable foregroundDrawable = ((AdaptiveIconDrawable) drawableIcon).getForeground();
Drawable[] drawables = new Drawable[2];
drawables[0] = backgroundDrawable;
drawables[1] = foregroundDrawable;
LayerDrawable layerDrawable = new LayerDrawable(drawables);
int width = layerDrawable.getIntrinsicWidth();
int height = layerDrawable.getIntrinsicHeight();
bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
layerDrawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
layerDrawable.draw(canvas);
}
else{
bitmap = Bitmap.createBitmap(drawableIcon.getIntrinsicWidth(), drawableIcon.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
}
}
else{
bitmap = Bitmap.createBitmap(drawableIcon.getIntrinsicWidth(), drawableIcon.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
}
}
catch(Exception e){
e.printStackTrace();
}
return bitmap;
}
Code:
public String [B]appName[/B](String pack){
String Name = null;
try{
PackageManager packManager = context.getPackageManager();
ApplicationInfo app = context.getPackageManager().getApplicationInfo(pack, 0);
Name = packManager.getApplicationLabel(app).toString();
}
catch(Exception e){
e.printStackTrace();
}
return Name;
}
Thanks for Support my Projects​Don't forget to Hit Thanks​
Reserved

Categories

Resources