I'm using the Android Developers Tab Layout tutorial to develop something/learn how to use layouts: http://developer.android.com/resources/tutorials/views/hello-tabwidget.html
I can get the tutorial working fine but I'm trying to extend the function of the interface.
I have 3 tabs - Main, Sub1 and Sub2.
Main just has info on it, it's an "about" section if you like.
But Sub1 and Sub2 are top tier subsections and I want to have buttons in them that take you to the content. The hierarchy is this:
Main
- Content "about"
Sub1
- Content A
- Content B
Sub1
- Content A
- Content B
This is what it looks like at present (placeholder icons atm):
The main.xml has TabHost as it's parent layout although the Main, Sub1 and Sub2 sections are ScrollViews. This is in line with the Android Dev tutorial.
Now if I create a content_a.xml does this still need to be in a TabHost? What I'd like is 2 types of content - Content A will just be text and Content B will be technical image that you can zoom and pan around, and I'd like the 3 main tabs to remain at the top.
I'd also like the option of leaving the tab layout altogether if the user presses a content button.
I get an error in Eclipse that reads: 07-21 11:23:42.278: ERROR/AndroidRuntime(19259): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.mine.app/com.mine.app.Content_a}: java.lang.RuntimeException: Your content must have a TabHost whose id attribute is 'android.R.id.tabhost'
I don't see why I have to stick to using a TabHost anyway, but does anyone have any ideas?
Seriously? No one knows how to do this?
I can't find the answer anywhere on the net and it cannot be possible that you have to only have content in the original tabs.
Come on people, someone must know.
I personally haven't played with tabs. I recommend you asking the same question over at stackoverflow if you don't get an answer here.
soo im a bit confused by your question. are those buttons in the image just place holders that you want to replace with other content? or do you want them to link to a another activity that will display either content A or content B. both are do-able.
if its the latter, just replace the xml for the buttons with whatever content you want them to be. TextView and ImageView.
if its the former, then make 2 new Activities (ContentA and ContentB) they will setContentView to what ever Layouts you want them to display. then tie the onClickListener to each button in your TabHost Activity to call startActivity()
Code:
Intent myIntent = new Intent(TabHostActivity.this, ContentA.class);
startActivity(myIntent);
then when you press the back button it should jump you back into your TabHost Activity
----
also, when do you get that error. what are you doing when it happens? just telling us what the error is is only half the story
I'll explain things a bit better.
I want this layout
Main
- Content "about"
Sub1
- Button to Content A
-- Content A
- Button to Content B
-- Content B
Sub2
- Button to Content C
-- Content C
- Button to Content D
-- Content D
The tabs switch between Main, Sub 1 and Sub 2.
Sub 1 and 2 are top-tier menus. Let's call it Cars and Motorbikes.
In the Cars tab I want a list of cars on buttons. Pressing a button takes you to info about that particular car, let's say a Mazda6 (as an example).
Ideally I'd like the tabs to remain at the top of the screen with the info about the Mazda6 below them. If you press the "back" button it takes you back to the list of cars, if you press a tab you can jump straight to that section (Main or Motorbikes for example)
If you've selected Mazda6 and exited that section by pressing a tab, pressing the Car tab should take you back to the Mazda6 content bypassing the button list.
Some of the Mazda6 content will have a pinch to zoom image.
I hope that's clearer.
The error I'm getting is when I press the Content buttons (the Mazda6 button for example). The way I've set it up is when you press a button it (attempts) to start a new activity:
Code:
public void onClick(View v) {
switch (v.getId()) {
case R.id.mazda6_button:
Intent b = new Intent(this, Mazda6.class);
startActivity(b);
break;
case R.id.mazda3_button:
Intent c = new Intent(this, Mazda3.class);
startActivity(c);
break;
}
This code works fine if I just have a list of buttons that switch between FrameLayout xml files, but I get an error only when using Tabs
Any feedback?
are your new activities declared in the AndroidManifest.xml?
Code:
<activity android:name=".Mazda6"></activity>
<activity android:name=".Mazda3"></activity>
killersnowman said:
are your new activities declared in the AndroidManifest.xml?
Code:
<activity android:name=".Mazda6"></activity>
<activity android:name=".Mazda3"></activity>
Click to expand...
Click to collapse
And if it isn't this, what's the Error you're getting?
My manifest file is fine. I learned not to make that error pretty quick.
This is the error.
Code:
ERROR/AndroidRuntime(19259): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.mine.app/com.mine.app.Content_a}: java.lang.RuntimeException: Your content must have a TabHost whose id attribute is 'android.R.id.tabhost'
Subjective Effect said:
My manifest file is fine. I learned not to make that error pretty quick.
This is the error.
Code:
ERROR/AndroidRuntime(19259): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.mine.app/com.mine.app.Content_a}: java.lang.RuntimeException: Your content must have a TabHost whose id attribute is 'android.R.id.tabhost'
Click to expand...
Click to collapse
This sometimes happens by bad generated R.java
Try deleting it. Happened to me like 1000 times with no errors on Code. if it isnt this, post your whole class / xml layout
D4rKn3sSyS said:
This sometimes happens by bad generated R.java
Try deleting it. Happened to me like 1000 times with no errors on Code. if it isnt this, post your whole class / xml layout
Click to expand...
Click to collapse
Always a good fallback position to delete and rebuild R.java
From something awesome
in the tabhost documentation there is a reference to setup() that needs to be called before any tabs are added to the tabhost when not using getTabHost()
you might want to try replacing getTabHost()
with
Code:
mTabHost = (TabHost)findViewById(R.id.tabhost);
mTabHost.setup();
I don't understand that. What exactly do I replace and what consequences does it have for the rest of my code?
I've tried replacing
Code:
TabHost tabHost = getTabHost();
with
Code:
mTabHost = (TabHost)findViewById(R.id.tabhost);
mTabHost.setup();
but that just produced a whole load of other errors.
killersnowman said:
Always a good fallback position to delete and rebuild R.java
From something awesome
Click to expand...
Click to collapse
how do you rebuild it? this is the most annoying thing when developing android.
Sent from my SGH-T959 using XDA App
To the OP.
What do you want to do when you click the button? Do you want to display a new screen then the text? or you want the same screen and a text will just pop out?
Sent from my SGH-T959 using XDA App
I want the new content to be displayed, but maintain the top tabs.
I can get it so that new content its displayed by linking the buttons to a new activity.
It's getting it to work with the tabs that is the problem.
Sent from my HTC Sensation Z710e using Tapatalk
What's the code for the button click?
As an alternative to the way you are doing it, you could setup different layouts and call to setContentView() again.
Basically the activity inside the tab could function as a "dynamic" holder of other content/layouts. Rather than changing activities with each button click.
It has different pros and cons but it's an option.
hth
I'll post the code later then.
I'd be open to altering the content in the current view for sure. I do want the buttons to link to pinch to zoom images though. Don't know if this wii be easy. I have out working without the tabs remaining.
Sent from my HTC Sensation Z710e using Tapatalk
Related
Hi all,
I am using eVC++ 4.0, and i've dynamically created a CListView like this:
Code:
lv.Create(0,_T(""),WS_CHILD|WS_VISIBLE,r,this,5);
but I dont know how to handle the events of this control... any ideas??
Mohammad
To get events from a listview (win32) I normally subclass it. I use the subclassing routine to post a message back to the parent when the user is doing something like tapping on it, then the windows routine can check whats selected etc and act on it. Is subclassing possible in mfc ?( I don't use it).
Thank u
but can anybody post some code??
thnx
Ok, I am a bit lazy to look up code at the moment, but here's something:
Yes, subclassing is possible in MFC. You just derive your class from the basic class provided like this:
Code:
class MyListView : pubic CListView
Then you add message handlers in the normal matter.
EDIT: The following passage is incorrect:
But I think subclassing may not be necessary in you case. List box controls send WM_COMMAND messages with notifications of major events like selection change to the parent window. All you have to do is to create a WM_COMMAND handler in your parent class.
Sorry I was thinking of ListBox not list view when I wrote it.
To manually add message handlers you need to put macros like ON_MESAGE or ON_COMMAND in the DECLARE_MESSAGE_MAP section of the class cpp file. All the detaisl are available on MSDN.
Are you saying that a listview will send the same WM_COMMAND as a list box in mfc? Dose this also happen in win32 made listviews. I have always thought it was a bit too tedious to find out when the user taps an item in the listview.
After reading your post levenum I had a quick look and it says that a WM_NOTIFY gets sent to the parent with a LVN_ITEMCHANGED for example. I had not used the LVN_**** because when I looked at them there was none that seem to deal with selections. I would guess that LVN_ITEMACTIVATE or LVN_ODSTATECHANGED would be usefull for this but then a second tap would not be picked up still leaving me wanting subclassing in many situations to get the users tap.
Ok, I have read what u wrote guys and my problem is almost solved, I used the OnNotify() method to handle messages sent from child controls like this:
Code:
BOOL CTest2Dlg::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
// TODO: Add your specialized code here and/or call the base class
if(wParam ==5 ) //5 is control ID
{
NMHDR *ph =(NMHDR*)lParam;
if(ph->code==NM_CLICK)
MessageBox("Click");
else if(ph->code==HDN_ITEMCLICK)
MessageBox("Item Click");
else
{
CString str;
str.Format("%d",ph->code);
MessageBox(str);
}
}
return CDialog::OnNotify(wParam, lParam, pResult);
}
Now there still a very small prolem: what messages should I handle for 'Selected Item Changed' event ?? I know its easy but I couldnt find it
Regards
mohgdeisat: I am sorry, I made a mistake about WM_COMMAND.
OdeeanRDeathshead is right, I was thinking of a list box not list view.
To make up for this, here is some sample code from a win32 dialog app that uses list view control. I hope it will be of some help:
Code:
//this is from the dialog window function:
case WM_NOTIFY: //handle events:
nmhdr = (LPNMHDR)lParam;
switch (nmhdr->idFrom)
{
case IDC_LEDLIST: //list control ID.
return OnLEDListEvent(hwndDlg, (LPNMLISTVIEW)lParam);
break;
}
break;
BOOL OnLEDListEvent(HWND hwndDlg, LPNMLISTVIEW nmlv)
{
/////
// Handles list view control notification messages
switch (nmlv->hdr.code)
{
case LVN_ITEMCHANGED:
return OnLEDListItemChanged(hwndDlg, nmlv);
break;
}
return 0;
}
BOOL OnLEDListItemChanged(HWND hwndDlg, LPNMLISTVIEW nmlv)
{
if (ListView_GetSelectionMark(nmlv->hdr.hwndFrom) != nmlv->iItem) return 0;
/* do what you need here */
return 0;
}
Don't mind the fact that I used 3 different functions. This is part of a bigger program and I am trying to keep things well organized without resorting to classes.
As I understand it, LVN_ITEMCHANGE is received for different reasons so I try to handle only the one coming from selected item. LVN_ITEMACTIVATE is only sent when you double click the item so if you just want to catch selection change you need to use LVN_ITEMCHANGE.
Once again, sorry for confusing you before.
thanx pals, good job!!!
I think my problem is now solved with ur help :wink:
Mohammad
Ok guys, I said that my problem was solved, yet, another problem arises...
When the list view is in the report mode, how can I determine when a header button is clicked, and determine which one was clicked???????
thanx in advance
To identify a header column click, you need to handle the WM_NOTIFY/HDN_ITEMCLICK message. Normally this message will be received by the header's parent control (i.e. the listview) -- some frameworks may redirect the message to the header control itself. I haven't worked with MFC in 10 years so I can't really if it reflects notification messages back to the control.
If you're trying to implement column sort, do yourself a favor and check out the Windows Template Library (WTL) at sourceforge.net. It's a set of C++ template classes that provide a thin yet useful wrapper around the standard Windows UI components. One of the classes is a sortable listview control. I've been using WTL with big Windows for more than 5 years -- you couldn't pay me to go back to MFC.
hi,
I have seen the WTL library and it seems very useful and time-saver, but I have a couple of questions about it:
1. can WTL 8.0 be installed with VC++ 6.0, specifically the appwizard stuff??how?? I see only javascript files of vc7.0 and 7.1 and 8.0!!
2. is there a good documentation about those classes??
Mohammad
I don't know about WTL 8; I'm still using WTL 7.5 with VS .Net 2003 for all my Win32 development. My guess is that it wouldn't work too well, as WTL is based on ATL, which has substantially changed between VC 6 and 7.
Good references for WTL include www.codeproject.com/wtl, and the WTL group over at Yahoo groups (reflected at www.gmane.org).
Some background: 10 years ago I had classes in basic, pascal, and c++( I missed something simple some where with functions or classes which messed me up in this I believe.)
So far I've watched a tutorial and set up my emulator and eclipse..
http://www.youtube.com/watch?v=z7bvrikkG7c
I then did a tutorial that ran my first program helloworld
http://www.youtube.com/watch?v=2gdhvwYUNJQ
I then did a tutorial and made a simple program that changes between two screens on a button click ( Why it is an hour long is beyond my understanding)
http://www.youtube.com/watch?v=m-C-QPGR2pM
I've proceeded to learning how to create menus and simply retrieved example code from the Google android site
Source: http://developer.android.com/guide/topics/ui/menus.html
Here's an example of this procedure, inside an Activity, wherein we create an Options Menu and handle item selections:
/* Creates the menu items */
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, MENU_NEW_GAME, 0, "New Game");
menu.add(0, MENU_QUIT, 0, "Quit");
return true;
}
/* Handles item selections */
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case MENU_NEW_GAME:
newGame();
return true;
case MENU_QUIT:
quit();
return true;
}
return false;
}
Click to expand...
Click to collapse
As I copy and pasted it into ecplise within an Activity, I realize there is some assumed information that I am missing when i received a bunch of errors
So.. I found A video tutorial
http://www.youtube.com/watch?v=6UYNnQOxCS8
and it instructs me to make sure I put these two lines of codes in first
Private static final int MENU1 = MENU.FIRST;
private static final int MENU2 = MENU.FIRST + 1;
I under line the menu's because it gives me errors on them as well... there seems to be some assumed knowledge I'm missing as well....
What specific piece of information am I missing to not have known that i would need those two lines as well as what I need to do to know the appropriate fix out of the suggestions they give me...
Are there any online tutorials or videos that'll bring me up to speed specifically with programming android apps... all the stuff I find just keeps leading me down a path to where I realize I've gotten ahead of myself because people are teaching things while assuming certain knowledge is known.
The tutorial I am following and getting errors on is for an 8th grade class of students...
Me: I'm pissed at that java toturial...
http://forum.xda-developers.com/showpost.php?p=6521891&postcount=6
Bastards.
Following the suggestion from this post
http://forum.xda-developers.com/showpost.php?p=6522089&postcount=7
I obtained a copy of Hello android.
Following the example to create a menu I used the code
I place this into my strings.xml
<string name="settings_label">Settings...</string>
name="settings_title">Sudoku settings</string>
<string
<string name="settings_shortcut">s</string>
<string name="music_title">Music</string>
<string name="music_summary">Play background music</string>
<string name="hints_title">Hints</string>
<string name="hints_summary">Show hints during play</string>
Click to expand...
Click to collapse
I place this into my main.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/settings"
android:title="@string/settings_label"
android:alphabeticShortcut="@string/settings_shortcut" />
</menu>
Click to expand...
Click to collapse
I import this files into my src app.java
right uner the other imports
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
Click to expand...
Click to collapse
I place this inside my activity ( where I think it would belong since it doesn't say where to put it. ) and ERROR
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
return true;
}
Click to expand...
Click to collapse
Quick fix says that menu needs to be either a field or constast so i give it a go and click field and it modifies a file called R.java.
I go back to app.java and not only is the menu highlighted but now R.menu.menu is entirely highlighted and says cannot be resolved or is not a field..
I try to modify the R.java file to remove what its done...
It won't let me..
Epic fail. on the third tutorial to create a menu.
I guess ill redo everything in a new project and then do the quick fix making menu a constant....
[edit] never mind ill look else where for help
http://www.youtube.com/watch?v=X3QO0ffg2Tc&feature=related
ok the toturial looks like it will work but when he types in this line in his app.java
public boolean onCreateOptionsMenu(Menu menu) {
Click to expand...
Click to collapse
it is under lined with an error on his screen as well as mine and then he says he is importing the missing classes and the error just disappeas with no demonstrations of what missing classing or what key combination he used to import them...
http://www.google.com/#hl=en&q=impo...=f&aqi=&aql=&oq=&gs_rfai=&fp=d059ab474882bfe2
WOO HOO found what he left out...
Compiled and installed...
Boo hoo menu key does nothing!! time to go back through the other menu tutorials and see if i cant get it working now that i know of this hot key..
Went back to this toturial with the elusive import missing classes hotkey..
http://www.youtube.com/watch?v=6UYNnQOxCS8
It worked like a charm
just had to remove
newGame();
and
quit();
and i have buttons that do nothing so far
More missing pieces.
I created a new activity as shown to me in previous tutorials giving it its own seperate XML file in the res/layouts as well as a jave file and I made sure it is calling for the right layout.
I also added the activity in the androidmanifest as shown to me as well..
off this site
http://developer.android.com/guide/topics/ui/menus.html
I've taken the code to create menus.. ( i got it working )
I then followed this and made the changes
Set an intent for a single menu item
If you want to offer a specific menu item that launches a new Activity, then you can specifically define an Intent for the menu item with the setIntent() method.
For example, inside the onCreateOptionsMenu() method, you can define a new menu item with an Intent like this:
MenuItem menuItem = menu.add(0, PHOTO_PICKER_ID, 0, "Select Photo");
menuItem.setIntent(new Intent(this, PhotoPicker.class));
Android will automatically launch the Activity when the item is selected.
Note: This will not return a result to your Activity. If you wish to be returned a result, then do not use setIntent(). Instead, handle the selection as usual in the onOptionsMenuItemSelected() or onContextMenuItemSelected() callback and call startActivityForResult().
Click to expand...
Click to collapse
It doesn't work... I don't understand why the intent would be in the onCreateOptionsMenu... it doesn't seem to work so I tried the alternative and replaced setIntent with with startActivityForResult.. and then I noticed it says "As usual" in the onOptionsMenuItemSelected()... which is where I would think the code would belong in the first place... but when I originally failed and tried to move the code there it errors...
Is ever step of the way really going to be half assed instructions.. i was beginning to think I had the hang of this.
Are the instructions bad or am i missing something???
Guess ill go dig in my hello android book.
EDIT: Wow that helped
startActivity(new Intent(this, register.class));
Click to expand...
Click to collapse
guess that book is worth something after all...
guess im just intending to start an activity with a particular intent and setting an intent alone isn't going to start the activity.... i suppose there must be some purpose behind setting an intent as they had describe on the google page.. just not seeing it yet...
Got to what i wanted tho.
Hi,
I have been trying to get to grips with Android.
First off I guess, any good books you can recommend? I have Hello, Android which has some good examples, but some of the things leave me a little cold in that it seems overly simplistic and then seems to fail to pick up on some latter crucial points, not least about creating custom adapters.
Anyhow, back to the questions.
Firstly, various devices, like the Samsung Galaxy S uses a "blue" summary line in its settings menus. Looks good. But if you want to mimic that style outside of a summary menu, is it possible to get details of system colours?
Secondly, in terms of icon design, tab icons in as defined in the Android SDK seem to suggest using a Grey icon for off and a white icon for on. This seems to bit a bit foolish when the tabs are white.... and most of the other programs I've seen that use tabs have Grey icons for on and white icons for off! Thoughts?
Third, back to this book, one of the examples it gives, is a way to load data from a SQL database using Cursors and SimpleAdapters. Im guessing if I want anything more than a relatively simple list and data pulled from the database, that Im going to need to use a CustomAdapter.
In terms of these cursors though, some of the code does this in the onCreate:
Code:
Cursor cursor
CustomDatabaseHelper test = new CustomDatabaseHelper(this);
try {
cursor = getData();
showData(cursor);
} finally {
test.close();
}
I think I found a couple of problems with that... The CustomDatabaseHelper and Cursor are both local to the onClick method and therefore if I need to access these via a Buttons onClick Im stuffed unless I make them private/public to the class. I don't know the best way around this TBH, what would you suggest? I guess I could define another CustomDatabaseHelper in the onClick method, but Im not sure whether it is a good idea to keep opening all these references.
Plus as well in onClick, you can't give a context of "this" because it's it's not a context there its an OnClickListener?
Code:
btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
}
}
And there must be a better way of refreshing the data set? I've tried cursor.notify, test.notify and globalising the adapter and doing adapter.notifyDataSetChanged(); things still don't refresh.
Im going to guess this is a pretty basic and common issue for newcomers trying to understand this that super context intent.
I think Im getting there, Im just trying to get a bit of background to a few of the basic issues Im having a bit of trouble with and find out what the best way to handle the issues are.
Oh, the showData function (which I call after any data change at the moment), does this:
Code:
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.test_item, cursor, Columns, TO);
I think that'll do for now, as my next issues are about SQL, Dates and Formatting.
Thanks
Simon
I think my problem stems around this book of mine... I can do a "notifyDataSetChanged()" on the adapter provided I don't do the "test.close" as above.
This suggests to me the DB Helper should be open across the activity lifetime.
Is that right?
My app uses the ActionBarCompat and NavigationDrawer, which begs the question of how is one supposed to structure the navigation? I see two options:
1) Use a single Activity and swap out Fragments.
2) Use multiple Activities, and transition between them.
The latter seems to be the correct way, however this means that each Activity must get and build the ActionBar and NavigationDrawer when called from another Activity.
How will this affect my transition animations? If I have a left-to-right transition effect when a navigation item is clicked, will it transition the entire Activity or everything below the ActionBar?
The former seems fraught with issues. A single .java class file could get really heavy and difficult to manage.
But while we're on the subject of Fragments, please consider this situation and school me on proper Fragment management:
A blank Activity with just a LinearLayout attaches a new Fragment to it that contains a Button. Inside the Fragment class, this button gets an onClickListener and when the button is clicked, another of the same kind of Fragment should be attached to the LinearLayout inside the Activity.
A) Should the Fragment class communicate to the Activity that a new Fragment should be attached? This could be done with a custom public interface and the callback being executed within the onClickListener in the Fragment class.
B) Or, should the Fragment handle attaching the new instance inside the onClickListener, making the Activity work less? By simply bridging the clicked Button and calling .getParent() until the LinearLayout is reached, then attaching it there.
The correct way is the former. You should use fragments with the navigation drawer. If you use activities you are going to setup the navigation drawer every new activity. You should open other fragments from the activity and not from the fragment itself. I believe their is a tutorial on the android developer site that explains this in depth. A quick Google search for "android fragment to fragment communication" or something like that should get you to it. I'll try and find a link later when I am on my computer if you don't find anything
Sent from my Nexus 7 using XDA Premium HD app
I have found a Gallery App on GitHub (https://github.com/sevenler/Android_Gallery2D_Custom) that I have integrated into my own app.
Currently the gallery displays all images from my device. What I would like to have is that it ONLY display the images starting at the folder on my sdcard that I specify such as..
private static String targetPath = Environment.getExternalStorageDirectory().toString() + "/DCIM/_private/.nomedia";
I tried several different modifications but I am really struggling.
I was hoping someone could take a look at the source code for the Gallery App on GitHub and tell me how to change it so it does not scan my entire device.
Thanks in advance!!
-Steve
StEVO_M said:
I have found a Gallery App on GitHub (https://github.com/sevenler/Android_Gallery2D_Custom) that I have integrated into my own app.
Currently the gallery displays all images from my device. What I would like to have is that it ONLY display the images starting at the folder on my sdcard that I specify such as..
private static String targetPath = Environment.getExternalStorageDirectory().toString() + "/DCIM/_private/.nomedia";
I tried several different modifications but I am really struggling.
I was hoping someone could take a look at the source code for the Gallery App on GitHub and tell me how to change it so it does not scan my entire device.
Thanks in advance!!
-Steve
Click to expand...
Click to collapse
I had a look at the source and from my understanding the important class here is that DataManager class here. Especially the getTopSetPath() with the static final Strings and maybe the mapMediaItems() methods seem to be where you need to look at. You might have to play around a bit, but this is where I would start.
SimplicityApks said:
I had a look at the source and from my understanding the important class here is that DataManager class here. Especially the getTopSetPath() with the static final Strings and maybe the mapMediaItems() methods seem to be where you need to look at. You might have to play around a bit, but this is where I would start.
Click to expand...
Click to collapse
I have tried adding/changing the following
Added...
//Setting Folder Path
public static final String targetPath = Environment.getExternalStorageDirectory().toString() + "/DCIM/_private/.nomedia";
Changed...
// This is the path for the media set seen by the user at top level.
private static final String TOP_SET_PATH = targetPath;
private static final String TOP_IMAGE_SET_PATH = "/combo/{/mtp,/local/image,/picasa/image}";
private static final String TOP_VIDEO_SET_PATH = "/combo/{/local/video,/picasa/video}";
private static final String TOP_LOCAL_SET_PATH = "/local/all";
private static final String TOP_LOCAL_IMAGE_SET_PATH = "/local/image";
private static final String TOP_LOCAL_VIDEO_SET_PATH = "/local/video";
I even tried setting all of the _PATH s to my targetPath
And I get a NullPointerException
12-13 11:07:47.881: E/AndroidRuntime(23029): Caused by: java.lang.NullPointerException
12-13 11:07:47.881: E/AndroidRuntime(23029): at com.myprivgallery.common.Utils.checkNotNull(Utils.java:48)
Which leads me to this in Utils.java
line 46 // Throws NullPointerException if the input is null.
line 47 public static <T> T checkNotNull(T object) {
line 48 if (object == null) throw new NullPointerException();
line 49 return object;
line 50 }
So if I am reading correctly, it is saying the path is empty. But I know that path works in other apps and it is not empty.
StEVO_M said:
I have tried adding/changing the following
Added...
//Setting Folder Path
public static final String targetPath = Environment.getExternalStorageDirectory().toString() + "/DCIM/_private/.nomedia";
Changed...
// This is the path for the media set seen by the user at top level.
private static final String TOP_SET_PATH = targetPath;
private static final String TOP_IMAGE_SET_PATH = "/combo/{/mtp,/local/image,/picasa/image}";
private static final String TOP_VIDEO_SET_PATH = "/combo/{/local/video,/picasa/video}";
private static final String TOP_LOCAL_SET_PATH = "/local/all";
private static final String TOP_LOCAL_IMAGE_SET_PATH = "/local/image";
private static final String TOP_LOCAL_VIDEO_SET_PATH = "/local/video";
I even tried setting all of the _PATH s to my targetPath
And I get a NullPointerException
12-13 11:07:47.881: E/AndroidRuntime(23029): Caused by: java.lang.NullPointerException
12-13 11:07:47.881: E/AndroidRuntime(23029): at com.myprivgallery.common.Utils.checkNotNull(Utils.java:48)
Which leads me to this in Utils.java
line 46 // Throws NullPointerException if the input is null.
line 47 public static <T> T checkNotNull(T object) {
line 48 if (object == null) throw new NullPointerException();
line 49 return object;
line 50 }
So if I am reading correctly, it is saying the path is empty. But I know that path works in other apps and it is not empty.
Click to expand...
Click to collapse
I don't think you can call an Environment method when static class variables are Initialised make sure that your String is the correct path with Logs, I would probably make that an instance variable instead...
SimplicityApks said:
I don't think you can call an Environment method when static class variables are Initialised make sure that your String is the correct path with Logs, I would probably make that an instance variable instead...
Click to expand...
Click to collapse
It may kinda look like I know what I'm doing, but looks are deceiving.
I really have no clue what I am doing. I consider myself a hack. I can some what look at code and then make it do what I want, but to actually program something new... I will see if I can't figure that out. But I really do appreciate your help.
StEVO_M said:
It may kinda look like I know what I'm doing, but looks are deceiving.
I really have no clue what I am doing. I consider myself a hack. I can some what look at code and then make it do what I want, but to actually program something new... I will see if I can't figure that out. But I really do appreciate your help.
Click to expand...
Click to collapse
Well then you should probably get started on a simpler app you've built yourself rather than trying to understand this very complex Gallery app (which in my view is poorly commented and documented)...
I had a closer look at the source and it seems that we are on the right track because the _PATH s are used in the getTopSetPath method of the DataManager, and a search reveals that it is called by various activities and pickers. If you're using one of those in your app we should be right.
Now let's get back to the basics, when the app is launched, the default launcher activity is Gallery.java. During it's creation, either startDefaultPage, startGetContent or startViewAction is called, but all of them have the following call:
Code:
data.putString(AlbumSetPage.KEY_MEDIA_PATH, getDataManager().getTopSetPath(DataManager.INCLUDE_ALL)); // or some other variable
So this is the path where the images are loaded. Honestly, I have no idea what the
Code:
"/combo/{/mtp,/local/all,/picasa/all}"
is doing in the path variable, it has to do something with the Combo classes in the data folder, since the app is loading images from different dirs. You can now call your Environment call there and somehow pass back Strings instead of Paths, but it would be nicer if we could somehow figure out the these Paths are used here. An important class is the LocalPhotoSource.java. That is also where getImage from the DataManager is called. You could have a look at that class as well. Which path do you want the gallery to scan actually? The best solution would be to further experiment with the _PATH String, without calling Environment as well as debugging the whole app from the start, so you can get an idea of how everything is working.
SimplicityApks said:
Well then you should probably get started on a simpler app you've built yourself rather than trying to understand this very complex Gallery app (which in my view is poorly commented and documented)...
I had a closer look at the source and it seems that we are on the right track because the _PATH s are used in the getTopSetPath method of the DataManager, and a search reveals that it is called by various activities and pickers. If you're using one of those in your app we should be right.
Now let's get back to the basics, when the app is launched, the default launcher activity is Gallery.java. During it's creation, either startDefaultPage, startGetContent or startViewAction is called, but all of them have the following call:
Code:
data.putString(AlbumSetPage.KEY_MEDIA_PATH, getDataManager().getTopSetPath(DataManager.INCLUDE_ALL)); // or some other variable
So this is the path where the images are loaded. Honestly, I have no idea what the
Code:
"/combo/{/mtp,/local/all,/picasa/all}"
is doing in the path variable, it has to do something with the Combo classes in the data folder, since the app is loading images from different dirs. You can now call your Environment call there and somehow pass back Strings instead of Paths, but it would be nicer if we could somehow figure out the these Paths are used here. An important class is the LocalPhotoSource.java. That is also where getImage from the DataManager is called. You could have a look at that class as well. Which path do you want the gallery to scan actually? The best solution would be to further experiment with the _PATH String, without calling Environment as well as debugging the whole app from the start, so you can get an idea of how everything is working.
Click to expand...
Click to collapse
I tried Changing the following in LocalAlbumSet.java
public class LocalAlbumSet extends MediaSet {
public static final Path PATH_ALL = Path.fromString("/DCIM/_private/.nomedia/all");
public static final Path PATH_IMAGE = Path.fromString("/DCIM/_private/.nomedia/image");
public static final Path PATH_VIDEO = Path.fromString("/DCIM/_private/.nomedia/video");
and Changing all of the TOP_..._Path s to
// This is the path for the media set seen by the user at top level.
private static final String TOP_SET_PATH = "/local/all";
private static final String TOP_IMAGE_SET_PATH = "/local/image";
private static final String TOP_VIDEO_SET_PATH = "/local/video";
private static final String TOP_LOCAL_SET_PATH = "/local/all";
private static final String TOP_LOCAL_IMAGE_SET_PATH = "/local/image";
private static final String TOP_LOCAL_VIDEO_SET_PATH = "/local/video";
I now see Random Images from /DCIM/_private/.nomedia but not all of them, which is really confusing. But at least it's a start.
StEVO_M said:
I have found a Gallery App on GitHub (https://github.com/sevenler/Android_Gallery2D_Custom) that I have integrated into my own app.
Currently the gallery displays all images from my device. What I would like to have is that it ONLY display the images starting at the folder on my sdcard that I specify such as..
private static String targetPath = Environment.getExternalStorageDirectory().toString() + "/DCIM/_private/.nomedia";
I tried several different modifications but I am really struggling.
I was hoping someone could take a look at the source code for the Gallery App on GitHub and tell me how to change it so it does not scan my entire device.
Thanks in advance!!
-Steve
Click to expand...
Click to collapse
Android gallery will not scan any folder having a .nomedia file in it.
EatHeat said:
Android gallery will not scan any folder having a .nomedia file in it.
Click to expand...
Click to collapse
So I am guessing there is no way to Force your own instance to scan it????
StEVO_M said:
So I am guessing there is no way to Force your own instance to scan it????
Click to expand...
Click to collapse
Delete the .nomedia file.
Lol. Not an option if I want to hide my pic.
Sent from my HTCONE using Tapatalk
Not sure what you are trying to achieve, if you want to scan it then why would you want to hide it?
If you want to add an option to allow it to scan or not, you could backup the .nomedia to another directory and delete it for the time being.
Just an idea, can't say for sure. Didn't try it ever.
I have created an app to hide pictures. Currently I have a very basic gallery. I was trying integrate this gallery because it has a lot more option such as editing and adding filters and such.
Sent from my HTCONE using Tapatalk
StEVO_M said:
I have created an app to hide pictures. Currently I have a very basic gallery. I was trying integrate this gallery because it has a lot more option such as editing and adding filters and such.
Click to expand...
Click to collapse
Well why do you need to? Make your app fulfill only one purpose, so let it hide the pictures (I guess by moving a .nomedia file into the folder right?) and then just create a shortcut in your app to the gallery app so the user can still use their preferred one... Makes more sense to me and is way less work.
StEVO_M said:
I have created an app to hide pictures. Currently I have a very basic gallery. I was trying integrate this gallery because it has a lot more option such as editing and adding filters and such.
Sent from my HTCONE using Tapatalk
Click to expand...
Click to collapse
A far more simple and logical way would be to create a hidden folder on the SD card with a .nomedia file in it. Images/videos that are to be hidden can be moved to that location. This would keep it hidden from the gallery and can only be accessed through your private gallery.
For unhiding media, just move them back to their original folders.
Let me try to explain further... As I said, I have created an app already that does the Basic things.
My Application looks like a standard App, a "To Do List", but if you press and hold an Icon on the main screen it prompts you for a Password (These passwords are setup on first use).
Now... Depending on which password you enter, it will either take you to the hidden Gallery OR if you enter a different password it will take you to a Hidden To Do List. This is so anyone that may stumble upon your app, you can show them that it's has a hidden area of the app. This way they have no clue you really have a Hidden Gallery.
If you enter the Hidden Gallery password then it would of course, take you to the hidden gallery.
The Current Features are...
Import from Main Gallery
Pinch to Zoom
Swipe
Share
Restore back to Main Gallery
Delete
Quick Escape ------ "Quick Escape" can be activate 2 ways. If you shake the phone while in the Hidden Gallery, the image will change to an image of your choosing or the default one that is set during install. OR..... A less obvious "Quick Escape" ... While in the Hidden Gallery, press the volume up or down and the image will switch. Either way, once it is in that mode, you can not press back. the only way out it to press the home button. This is designed so if someone grabs the phone out of your hand they will only see they Quick Escape" image and pressing back will not take them back to the gallery.
My app also appears in the standard Share menu, so if you are in your Main Gallery and want to hide a picture, you can share it to my app and it will then hide the picture.
I want to add More features to my Gallery, such as Filters, Editing (crop, rotate...), Frames... All the same things that you can do in the Main Gallery. The only thing I really don't want or need is a Camera function. I can't see someone taking the time to open my app and then get to the Hidden Gallery and then taking a picture, just so they can hide an image. Most would just take the picture as they always would and then "Share" it to my app.
I hope this explains Why I want to use the other Gallery rather than reinventing the wheel that already has all of these features built in. If I can not get that to work, maybe I can just pull the Features out and use those.
Anyone who wants to actually See the app in action, PM me and I will send you a DropBox link to install. FYI, It requires 4.0 or higher.