am trying to access both the Phone's phonebook and SIM phonenook on Nokia 5130c-2 XpressMusic.
The app runs without errors but it only returns the numbers from the phone's Phonebook. When I list the available phonebooks using this code
String[] all_contact_lists=PIM.getInstance().listPIMLists(PIM.CONTACT_LIST);
it gives me both the Phonebook and SIM card lists. i.e
1. Phone
2. SIM
I have tried explicitly reading from the SIM card using this code but it still returns nothing(even though I have numbers saved in the SIM card.)
Code:
ContactList clist = (ContactList) PIM.getInstance().openPIMList(PIM.CONTACT_LIST, PIM.READ_ONLY,
"SIM");
Here's my complete code::
import javax.microedition.midlet.*;
import javax.microedition.pim.*;
import com.sun.lwuit.*;
import java.util.*;
public class contacts extends MIDlet
{
private List my_list=new List();
private String[] names=null;
public void startApp()
{
Display.init(this);
Form my_form=new Form("Contacts List");
String[] all_contact_lists=PIM.getInstance().listPIMLists(PIM.CONTACT_LIST);
//Iterate through available phonebooks
for(int db=0; db<all_contact_lists.length; db++)
{
try {
ContactList clist = (ContactList) PIM.getInstance().openPIMList(PIM.CONTACT_LIST, PIM.READ_ONLY,
all_contact_lists[db]);
Enumeration contacts=clist.items();
while(contacts.hasMoreElements())
{
Contact contact=(Contact)contacts.nextElement();
try{
String phone_contact="";
names=contact.getStringArray(Contact.NAME, 0);
for(int i=0; i<names.length; i++)
{
if(names[i]!=null)
phone_contact+=" "+names[i];
}
//my_list.addItem(phone_contact);
int phone_numbers=contact.countValues(Contact.TEL);
if(phone_numbers>0)
{
String number=contact.getString(Contact.TEL,0);
my_list.addItem(phone_contact+":"+number);
}
else
{
my_list.addItem(phone_contact);
}
//clist.removeContact(contact);
}
catch (Throwable t) {
t.printStackTrace();
}
}
} catch (PIMException ex) {
ex.printStackTrace();
}
}
//my_list.addItem(all_contact_lists);
my_list.setRenderingPrototype("WWWWWWWWWWWWWWWWWWWW");
my_form.addComponent(my_list);
my_form.show();
}
public void pauseApp(){}
public void destroyApp(boolean unconditional){}
}
If you are using the phone number for a text or to call you can do that with only one line of code. Its now evident that phone software issues can affect the way the app accesses the PIM API. Also, if memory in use in the phones contact settings is set to SIM(alone), you can't access contacts in phone memory and vice versa, make sure both are in use. Try this if you still have an issue,
//make a text field in LWUIT that is declared globally
PhnNmbr = new TextField();
//set it to only accept phonenumber
PhnNmbr.setConstraint(TextField.PHONENUMBER);
//tell the user how to access phonebook
PhnNmbr.setHint("Press T9 then 'Search' to search phonebook");
//add a button or command
//that either sends an sms to
//or calls the number in the text field
//or anything else you want to do with it
When the user presses T9, the TextField is considered an LCDUI text field with parameter PHONENUMBER which allows it to search for contacts in both Sim and phone memory, thats why you'll notice a Search command(usually at the bottom center). Also make sure that the memory in use for the phone is set to both Phone and Sim.
An excerpt from PIM javadoc
PIMItems reference its data through fields. A field is a grouping of
data values that all have similar characteristics. An example of a
field is TEL, which indicates data values for that particular field
are telephone numbers. Classes implementing the PIMItem interface
defines the possible fields that for that specific class (e.g TEL is
defined in the Contact interface as a field that a contact may
support).
PIM implementations are not required to support all of the possible
fields defined in the classes implementing the PIMItem interface. This
is because no native PIM databases contain all of the fields defined
in this API. The PIMList that a PIMItem belongs to determines what
fields a PIMItem can support and store (all PIMItems in a particular
PIMList support the same set of fields). The
PIMList.getSupportedFields() method from a particular PIMItem's
PIMList is used to find out what fields are supported within this
item. Since not all possible fields are actually supported in a
particular PIMItem, all fields should be checked for support in the
item's PIMList using PIMList.isSupportedField(int) prior to being used
in any retrieval or storage method.
Each field has the following pieces of information available for it:
Zero or more data values associated with the Field
Attributes for data values for the Field
Descriptive label for the Field
Data Type of the data associated with the Field
Complete PIM javadoc can be read at this link.
Check if the device support's PIM Fields Contact.NAME and Contact.TEL on your device. If not then you need to call PIMList.getSupportedFields() to get the supported field on device and accordingly fetch the name and the telephone number for that device. If I remember correct, the alternative field for name is Contact.FORMATTED_NAME.
Related
I am building a Generic Inquiry which would list the Contract Details with FixedRecurringPriceVal and UsrCustomFixedRecurringPriceVal. The later is a custom persistent field. Now, in this Generic Inquiry I would like to list only those Contract Details from Customer Contract which have different FixedRecurringPriceVal and UsrCustomFixedRecurringPriceVal.
But, those I can use FixedRecurringPriceVal in Results Grid, it appears that I can't use this field in Condition where I needed to compare between these fields.
Upon looking at Data field source I find this.
[PXDecimal(6)]
[PXFormula(typeof(GetItemPriceValue<
ContractDetail.contractID,
ContractDetail.contractItemID,
ContractDetailType.ContractDetail,
ContractDetail.fixedRecurringPriceOption,
Selector<ContractDetail.contractItemID, ContractItem.recurringItemID>,
ContractDetail.fixedRecurringPrice,
ContractDetail.basePriceVal,
ContractDetail.qty,
Switch<
Case<Where<Parent<Contract.status>, Equal<Contract.status.draft>,
Or<Parent<Contract.status>, Equal<Contract.status.pendingActivation>>>,
IsNull<Parent<Contract.activationDate>, Parent<Contract.startDate>>,
Case<Where<Parent<Contract.status>, Equal<Contract.status.active>,
Or<Parent<Contract.status>, Equal<Contract.status.inUpgrade>>>,
IsNull<Parent<ContractBillingSchedule.nextDate>, Current<AccessInfo.businessDate>>,
Case<Where<Parent<Contract.status>, Equal<Contract.status.expired>>,
IsNull<Parent<ContractBillingSchedule.nextDate>, Parent<Contract.expireDate>>,
Case<Where<Parent<Contract.status>, Equal<Contract.status.canceled>>,
IsNull<Parent<Contract.terminationDate>, Current<AccessInfo.businessDate>>>>>>,
Current<AccessInfo.businessDate>>>))]
[PXUIField(DisplayName = "Recurring Price")]
public decimal? FixedRecurringPriceVal
{
get;
set;
}
So, for me it looks like Non Persistent field can't be used in Generic Inquiry Conditions. I did a bit of google but couldn't find any solution and also looked at the S130 Data Retrieval and Analysis and couldn't find specific to such case.
Is there any way we can achieve this?
Thanks.
No, you can't use Non Persistent fields in the Conditions.
The field dropdown is intentionally excluding them. Below is the FieldSelecting event handler from the GenericInquiryDesigner graph which is loading the dropdown.
protected void GIWhere_DataFieldName_FieldSelecting(PXCache cache, PXFieldSelectingEventArgs e)
{
string[] allParameters = this.GetAllParameters(true);
PXStringListAttribute.SetList(cache, e.Row, typeof(GIWhere.dataFieldName).Name, allParameters, allParameters);
this.a<GIWhere.dataFieldName>(cache, e.Row, true, (PXCache c, string f) => !PXGenericInqGrph.IsVirtualField(c, f, null));
}
The only way, in this case, will be to create a separate page instead of GI.
I found it very odd that the base installation of Acumatica did not contain the ability to document approved Manufacturer/part number for Stock Items, so I added this functionality to my customization project. The design allows each branch to define their own approved manufacturers and part number, but I need to allow a user with access to only one branch to see the approved manufacturers from other branches.
My DAC's are SSINManufacturer (the manufacturer master) and SSINItemManufacturer (the individual branch specific manufacturer part number record for the Stock Item).
The customization was added as a new tab under Stocked Items as a grid view. Access control by branch (across the system) is handled via a user role for the branch, but I need allow any user with access to Stocked Items to see all manufacturer part numbers from any branch.
I found a post in AsiaBlog (https://asiablog.acumatica.com/2015/11/using-scopes-in-acumatica.html) that mentions the use of PXReadBranchRestrictedScope to "remove restriction by branches that will be automatically applied by the system core, if you have BranchID attribute in the selected DAC". I was advised not to use BranchID, but rather UsrBranchID in my custom DAC's, but I suspect this is the underlying reason that I'm still restricted to just the current branch data in this view.
I am just starting to learn to use a constructor to override the default results that a view would generate, and I'm not sure that this definition is correct.
public PXSelectJoin<SSINItemManufacturer,
InnerJoin<SSINManufacturer, On<SSINManufacturer.manufacturerID, Equal<SSINItemManufacturer.manufacturerID>>>,
Where<SSINItemManufacturer.inventoryID, Equal<Current<InventoryItem.inventoryID>>
>> ItemManufacturerXrefs;
public virtual IEnumerable itemmanufacturerxrefs()
{
using (new PXReadBranchRestrictedScope())
{
PXResult<SSINItemManufacturer> Results = PXSelectJoin<SSINItemManufacturer,
InnerJoin<SSINManufacturer, On<SSINManufacturer.manufacturerID, Equal<SSINItemManufacturer.manufacturerID>>>,
Where<SSINItemManufacturer.inventoryID, Equal<Current<InventoryItem.inventoryID>>
>>.Select(Base);
yield return Results;
}
}
Is the constructor defined correctly to leverage PXReadBranchRestrictedScope? And do I need to add BranchID to my DAC to make this return all records for the Stocked Item in the tenant?
Two issues found which resolved the problem. First, the PXResultset was defined as PXResult which returned only 1 value, and the subsequent method of returning the result needed to be expanded to more explicitly build the results to be returned.
public virtual IEnumerable itemmanufacturerxrefs()
{
using (new PXReadBranchRestrictedScope())
{
PXResultset<SSINItemManufacturer> Results = PXSelectJoin<SSINItemManufacturer,
InnerJoin<SSINManufacturer, On<SSINManufacturer.manufacturerID, Equal<SSINItemManufacturer.manufacturerID>>>,
Where<SSINItemManufacturer.inventoryID, Equal<Current<InventoryItem.inventoryID>>
>>.Select(Base);
foreach (PXResult<SSINItemManufacturer, SSINManufacturer> result in Results)
{
SSINItemManufacturer mfgitem = result;
SSINManufacturer mfg = result;
yield return new PXResult<SSINItemManufacturer, SSINManufacturer>(mfgitem, mfg);
}
}
}
Secondly, upon closer review of the post on AsiaBlog, the BranchID (actually Branch) ATTRIBUTE needed to be added to the field of the DAC. UsrBranchID is fine for a field name, provided the [Branch] attribute was added.
#region UsrBranchID
[Branch(IsKey = true)]
[PXDefault(typeof(AccessInfo.branchID))]
[PXUIField(DisplayName = Messages.FldUsrBranchID)]
public virtual int? UsrBranchID { get; set; }
public abstract class usrBranchID : PX.Data.BQL.BqlInt.Field<usrBranchID> { }
#endregion
The scope override works well. The use of the constructor on the view allows me to grant visibility to the data from all branches "as advertised".
Good day!
In my Orchard, I have several content types all with my custom part attached. This part defines to what users this content is available. For each logged user there is external service, which defines what content user can or cannot access. Now I need access restriction to apply everywhere where orchard display content lists, this includes results by specific tag from a tag cloud, or results listed from Taxonomy term. I seems can’t find any good way to do it except modifying TaxonomyServices code as well as TagCloud services, to join also my part and filter by it. Is this indeed the only way to do it or there are other solutions? I would like to avoid doing changes to built-in modules if possible but cannot find other way.
Thanks in advance.
I'm currently bumbling around with the same issue. One way I'm currently looking at is to hook into the content manager.
[OrchardSuppressDependency("Orchard.ContentManagement.DefaultContentManager")]
public class ModContentManager : DefaultContentManager, IContentManager
{
//private readonly Lazy<IShapeFactory> _shapeFactory;
private readonly IModAuthContext _modAuthContext;
public ModContentManager(IComponentContext context,
IRepository<ContentTypeRecord> contentTypeRepository,
IRepository<ContentItemRecord> contentItemRepository,
IRepository<ContentItemVersionRecord> contentItemVersionRepository,
IContentDefinitionManager contentDefinitionManager,
ICacheManager cacheManager,
Func<IContentManagerSession> contentManagerSession,
Lazy<IContentDisplay> contentDisplay,
Lazy<ISessionLocator> sessionLocator,
Lazy<IEnumerable<IContentHandler>> handlers,
Lazy<IEnumerable<IIdentityResolverSelector>> identityResolverSelectors,
Lazy<IEnumerable<ISqlStatementProvider>> sqlStatementProviders,
ShellSettings shellSettings,
ISignals signals,
//Lazy<IShapeFactory> shapeFactory,
IModAuthContext modAuthContext)
: base(context,
contentTypeRepository,
contentItemRepository,
contentItemVersionRepository,
contentDefinitionManager,
cacheManager,
contentManagerSession,
contentDisplay,
sessionLocator,
handlers,
identityResolverSelectors,
sqlStatementProviders,
shellSettings,
signals) {
//_shapeFactory = shapeFactory;
_modAuthContext = modAuthContext;
}
public new dynamic BuildDisplay(IContent content, string displayType = "", string groupId = "") {
// So you could do something like...
// var myPart = content.As<MyAuthoPart>();
// if(!myPart.IsUserAuthorized)...
// then display something else or display nothing (I think returning null works for this but
//don't quote me on that. Can always return a random empty shape)
// else return base.BuildDisplay(content, displayType, groupId);
// ever want to display a shape based on the name...
//dynamic shapes = _shapeFactory.Value;
}
}
}
Could also hook into the IAuthorizationServiceEventHandler, which is activated before in the main ItemController and do a check to see if you are rendering a projection or taxonomy list set a value to tell your content manager to perform checks else just let them through. Might help :)
I have extended the built-in User ContentType with a Content Picker Field that can be used to select multiple Video ContentItems. This gives me a video multi-picker control on the Edit page of each User.
I love how Orchard CMS makes this so elegantly simple to setup.
Now that I can associate multiple Videos with a User, I'd like to create a Query that will display just the Videos that the currently logged in User has been granted access.
I was hoping to be able to setup a Query using the Projector module, in what I thought was the obvious way (see below), but this returns no results.
This is how I configured the second filter:
Clicked on the + Add a new Filter link on the Edit Query screen
Chose Videos:Ids from the User Content Fields section, like this:
Configured the new filter like this:
What am I doing wrong, or what is the simplest way of diagnosing this issue?
This is how the Content Picker field is defined:
I have spotted my error - it was due to me not having a proper understand of how the filters worked. The Videos:Ids filter in the User Content Fields section does not give access to the current user's list of videos, as I assumed. Instead, it is offering the field to be used in the filter, which would be useful if I were to write a query to produce a list of Users that had access to a specific Video.
It was wishful thinking that it worked the way I wanted, but it's obvious in retrospect how it actually works.
Update: in the hope it's useful for others, here's the custom filter I developed:
public interface IFilterProvider : IEventHandler
{
void Describe(dynamic describe);
}
public class CurrentUserVideosFilter : IFilterProvider
{
private readonly IWorkContextAccessor _workContextAccessor;
public CurrentUserVideosFilter(IWorkContextAccessor workContextAccessor)
{
_workContextAccessor = workContextAccessor;
T = NullLocalizer.Instance;
}
public Localizer T { get; set; }
public void Describe(dynamic describe)
{
describe.For("My Filter Category", T("My Filter Category"), T("My Filter Category"))
.Element("Current User's Videos", T("Current User's Videos"), T("Current User's Videos"),
(Action<dynamic>)ApplyFilter,
(Func<dynamic, LocalizedString>)DisplayFilter,
null
);
}
public void ApplyFilter(dynamic context)
{
var query = (IHqlQuery)context.Query;
context.Query = query.ForType("Video")
.Where(x => x.ContentPartRecord<IdentityPartRecord>(), x => x.InG("Id", GetVideoIdsForCurrentUser()));
}
private IList<int> GetVideoIdsForCurrentUser()
{
var currentUser = _workContextAccessor.GetContext().CurrentUser;
if (currentUser == null) return new int[0];
dynamic item = currentUser.ContentItem;
var videoContentItems = (IEnumerable<ContentItem>)item.User.Videos.ContentItems;
return videoContentItems.Select(i => i.Id).ToList();
}
public LocalizedString DisplayFilter(dynamic context)
{
return T("Videos that have been assigned to the currently logged in user");
}
}
I created this class in a new Orchard module, which contains all my customisations for the site I'm building. Once I installed the module, the filter was immediately available. I assume Orchard uses reflection to seek out all types that implement the IFilterProvider interface.
This is how the filter appears on the Add a Filter screen:
Clicking on the filter shows this screen:
Once the filter has been saved, the query works exactly how I'd like - it shows all videos that have been assigned to the currently logged in user.
I have a business requirement to only send permissioned properties in our response payload. For instance, our response DTO may have several properties, and one of them is SSN. If the user doesn't have permissions to view the SSN then I would never want it to be in the Json response. The second requirement is that we send null values if the client has permissions to view or change the property. Because of the second requirement setting the properties that the user cannot view to null will not work. I have to still return null values.
I have a solution that will work. I create an expandoObject by reflecting through my DTO and add only the properties that I need. This is working in my tests.
I have looked at implementing ITextSerializer. I could use that and wrap my response DTO in another object that would have a list of properties to skip. Then I could roll my own SerializeToString() and SerializeToStream(). I don't really see any other ways at this point. I can't use the JsConfig and make a SerializeFn because the properties to skip would change with each request.
So I think that implementing ITextSerializer is a good option. Are there any good examples of this getting implemented? I would really like to use all the hard work that was already done in the serializer and take advantage of the great performance. I think that in an ideal world I would just need to add a check in the WriteType.WriteProperties() to look and the property is one to write, but that is internal and really, most of them are so I can't really take advantage of them.
If someone has some insight please let me know! Maybe I am making the implementation of ITextSerialzer a lot harder that it really is?
Thanks!
Pull request #359 added the property "ExcludePropertyReference" to the JsConfig and the JsConfigScope. You can now exclude references in scope like I needed to.
I would be hesitant to write my own Serializer. I would try to find solutions that you can plug in into the existing ServiceStack code. That way you will have to worry less about updating dlls and breaking changes.
One potential solution would be decorating your properties with a Custom Attributes that you could reflect upon and obscure the property values. This could be done in the Service before Serialization even happens. This would still include values that they user does not have permission to see but I would argue that if you null those properties out they won't even be serialized by JSON anyways. If you keep all the properties the same they you will keep the benefits of strong typed DTOs.
Here is some hacky code I quickly came up with to demonstrate this. I would move this into a plugin and make the reflection faster with some sort of property caching but I think you will get the idea.
Hit the url twice using the following routes to see it in action.
/test?role
/test?role=Admin (hack to pretend to be an authenticated request)
[System.AttributeUsage(System.AttributeTargets.Property)]
public class SecureProperty : System.Attribute
{
public string Role {get;set;}
public SecureProperty(string role)
{
Role = role;
}
}
[Route("/test")]
public class Test : IReturn
{
public string Name { get; set; }
[SecureProperty("Admin")]
public string SSN { get; set; }
public string SSN2 { get; set; }
public string Role {get;set;}
}
public class TestService : Service
{
public object Get(Test request)
{
// hack to demo roles.
var usersCurrentRole = request.Role;
var props = typeof(Test).GetProperties()
.Where(
prop => ((SecureProperty[])prop
.GetCustomAttributes(typeof(SecureProperty), false))
.Any(att => att.Role != usersCurrentRole)
);
var t = new Test() {
Name = "Joe",
SSN = "123-45-6789",
SSN2 = "123-45-6789" };
foreach(var p in props) {
p.SetValue(t, "xxx-xx-xxxx", null);
}
return t;
}
}
Require().StartHost("http://localhost:8080/",
configurationBuilder: host => { });
I create this demo in ScriptCS. Check it out.