Below issues have been discussed in isolation but I could not find a solution which works. Hence posting the complete story and list of issues.
We are building an SDK(midlet jar) to be consumed by multiple apps. This SDK uses persistent store to store certain data. Now couple of issues plaguing us:
1. The key to access the store has been hard-coded in the SDK. Now multiple apps try to access the store with same key value resulting in conflicting issues.
2. The Persistable object package/class name is the same in multiple apps. Because of this we get the "Class Multiply defined" error while launching the apps.
Now for 2, we have been mulling over below options but none of them seem to solve the issue:
1. Do not extend the standard objects like Vector and use standard objects.
Issue: recycling of data is lost causing conflicts.
2. Build the library with a unique name for each application that uses it.
Issues: This would mean we will have to release a different SDK for every client who wants to use it.
3. Check if the Persistable object class already exists before loading the package for the next app.
Issues: What happens when the first package is unistalled? the class type would be deleted?
4. Ask the app to implement the Persistable interface and also pass the key in a callback.
This does not sound right to ask the app to pass some values just because we are not able to use the persistent store.
So as of now SDKs using Persistable objects seems to be totally broken. Or are we missing something?
Any other alternative suggestion to achieve the task is also very welcome.
if there is a library which functionality can be shared among different applications then make it as a library cod file, and specify this cod file as a library upon compiling the dependent projects.
For instance, if the library name is mylib_version1_00.cod then your other projects could contain the following files after compilation:
for Project1:
project1.cod
mylib_version1_00.cod
for Project2:
project2.cod
mylib_version1_00.cod
......
for for ProjectN:
projectN.cod
mylib_version1_00.cod
upon installation of every project you will install mylib.cod file, and if there's already installed mylib.cod file it will be overwritten, and it will avoid "class xxx multiply defined".
This error occurs because all applications are running under one JVM instance. So if you are uploading to device a cod file with the name, that already exists, it will be rewritten.
In case you will release the next version of your library, name the cod file as
mylib_version2_00.cod
and use version number in package name, for instance:
com.yourcompany.yourpoduct.yourlibary.version1
com.yourcompany.yourpoduct.yourlibary.version2
In this case you can have on the same device cod files: mylib_version1_00.cod and mylib_version2_00.cod and it won't produce "class xxx multiply defined" error.
Now about the persistence. Do not hardcode persistence key in your library. Make an abstract class and declare an abstract method like:
public long getPersistenceKey();
which returns a unique persistence key for an object. And use this method call in the code that persists the information in your abstract class.
and in children classes, used in your custom applications just override this method with different values for every product. And there won't be confilcts anymore.
Hope this helps.
There can be only one persistable class with a given classname on the entire device. If two apps have the same class which are persistable, you'll get a Class Multiply Defined verification error and the second app will not install at all.
The only way is to use the builtin persistable classes for storing persistable data in the SDK. However, this persitable data will not be deleted even when all the apps containing the SDK have been removed by the user. You will also have to take care of the versions of the data to be backward compatible.
You store the data using a builtin class like Hashtable, IntHashtable or Vector. Then you write a wrapper class which gets and sets this information. Basically you'll be mapping your persistable class to a Hashtable or Vector.
Again remember, you should never put any class that is not builtin into this datastore. Otherwise, the datastore will get deleted on the app uninstall.
Hope that helps.
Related
I am a (very) novice iOS/Swift programmer with a basic question about moving reusable software objects to their own ... something.
I am developing three iPhone apps that present information from three distinct data sets. Those data sets contain unique information but are structurally similar. As such, the apps share some Swift classes that are identical, specifically the classes that model the data. As I continually refactor the code, I find that when I tweak a class in one app's project, I have to remember to go to the other two projects and make the same tweaks to the same classes for those apps. It's getting to be a big headache.
What I would like to do is have one class definition in its own ... something that I can share, link, import, or attach to/from each app's project. From my online research, I suspect that the ... something is a library? or maybe it's a framework? or a module? I have found all three terms are used, but I am not sure how they relate to each other.
Given that all of the software I am writing is in Swift, does Xcode support what I am trying to do? Thank you!
It seems you have the issue of needing the same Swift class in multiple projects. You could build a Framework (aka Module) for this class then copy it in to each project. This is probably the formally correct approach but it is a bit of overkill for just a single class.
Instead, you could just make the file in the Navigator panel a reference in each project to the one actual file.
You could also make a Workspace and then put each project into the workspace and just have the file at the top level (but this may introduce some build complexity).
I need to make several versions of an iOS application each with a different target and name. Most of the differences between the applications are in the applications resources and not the source code. I am trying to share as much source code across versions as possible.
My issue arises when I try to access the application object in a version which does not have the same name as the original. For instance, I have two versions of the application named UserApp and UserApp2 and the following code which references the data store:
var user = UserApp.User
When I try to run this code in the UserApp2 target, it throws an error saying UserApp is undefined.
My question is: How can I make this code load the proper application object depending on what target is currently running? I would like a solution that can be used across all targets without the need to change code.
EDIT: The UserApp object is an XCDataModel.
The UserApp class might not be added in all of your application targets. verify the target membership for the class.
I'm in process of making a new iOS tweak. I grabbed iOS Headers https://github.com/MP0w/iOS-Headers.
Later on I figured out another repository on Github named iOS Runtime Headers https://github.com/nst/iOS-Runtime-Headers
Now i'm confused. What is the difference between these two?
There are 3 main sources for headers: from the developer of the code, from class-dump, and from a runtime header dumping tool.
Apple or SDK developers will release a header file that includes the public interface they intend other developers to use. It might not include some methods/variable declarations they don't want you to see. UIView.h from Apple's SDK would be a great example of something they're hiding certain info from.
Just because they didn't include those methods in the header file, doesn't mean that instances of those classes can't respond to them. This is where a tool like class-dump comes in, which looks through the compiled Mach-O files to determine which methods/ivars the class contains, and generate a header according to that.
Entirely new classes, methods, and ivars can be added to removed during runtime, using Objective-C's runtime features. Things like categories that get loaded from other SDKs/object files won't appear in a class-dump of the original class either. For these reasons, runtime dumping tools can see what instances of these classes can actually respond to during runtime.
Each set of headers can be useful in determining the intended and unintended uses for a class, knowing the differences can help you get a clearer picture of whatever you're reverse engineering.
It's hard to say what the differences are. They are both sets of headers generated with runtime introspection. The first one says it's headers both public and private.
Just so everybody understands, both links point to sets of headers that give you access to private OS APIs. Using these will get you rejected from the app store. They're only really useful for developing apps for the developer's personal use, or for jailbroken development.
I just realized that Bundle Creator OS Type code in my iOS app's Info.plist value is ????? in Xcode 4. What is the value supposed to be?
It's used to identify your application. You don't have to change it for an iPhone application.
Take a look at these links:
Information Property List Key Reference
Mac Creator and File Type Codes
Data Type Registration
It's not really used anymore.
It's a holdover from the Classic Mac OS days
when it was a datapoint used mainly to determine what apps could create or edit or read file types.
Back then you had to register them with Apple.
I don't think they even provide that service any more.
OS X and some apps might still use it in rare cases under the hood but its very legacy.
As you can imagine, the severely limited possible permutations made it untenable long term.
UTIs are the preferred approach now. The system then uses a combination of these and file extensions and magic numbers. Though on ios that may not be true as much as OSX.
It is just the four letter code to identify the bunder creator... for example for apple it is APPL...
It can be ???? or if your app name is "myApp" you can give "MYAP"... If you have many apps you can give first 2 characters with your app name and next 2 characters with company name...
For example apple uses CF for core foundation, AV etc
http://developer.apple.com/library/ios/#documentation/general/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
Just to give the historical perspective on extensions and file type and creator codes.
File extensions were part of the file system in CP/M and were intended to function something like what file types and creator codes actually did in MacOS. At the time, it was expected that each application would use a unique extension and only the one application would ever edit its own files. In the file system, the file name and extension were stored in two different areas, so the extension was not part of the name. Remember, at that time most systems had only a few applications, and file contents were specific to an application. They were never intended to be visible to end users, but due to an error in the directory command in CP/M, they were shown displayed as if they were part of the file name. MS-DOS picked up the convention, and the rest, unfortunately is history.
Apple's initial file system design saw the shortcomings of the extension concept, the primary one being that some file types were likely to be used by more than one application and with standardization of file formats, having more than one application that could operate on a file would be common. Therefore Apple split the file creator - the app that created the file - from the file type. By default if a file was double clicked, the originally creating application would open it. However, if a user did a file open from within an application, then all compatible files were supposed to be listed, even if that app was not the creator. Also, it would be possible to list all the applications that could open a file. Semantically, as intended in CP/M, the type and creator codes were separate from the file name itself.
Developers that properly registered their applications with Apple got their own creator codes. The problems with this concept came about from two sources: 1. Developers that hijacked other's or Apples own creator codes. 2. Unix systems, which never had a formal filename extension (all file names were a single string) began adopting the convention to end the file name with a dot and some additional letters to indicate file type. In the Unix convention, the extension is part of the file name itself, unlike CP/M and MS-DOS.
We've signed a 4.7 Blackberry application with the 4.6 code-signing tool. But when starting the application a second time it throws a 'KeyCodeNumber exception'.
Anybody some clues to why we get this exception?
Thanks!
KeyCodeNumber exceptions have todo with the verification process.
Blackberry published an article describing how to prevent verification errors:
When developing Java applications for
the BlackBerry smartphone, you may
encounter any of the following
verification errors or errors similar
to the following:
Verification Error 3141 Module
'MyMIDlet' has verification error
(<###>) at offset <###>. Error
starting MyMIDlet: Module 'MyMIDlet'
has verification error (<####>) at
offset <###>." These errors often
occur when creating MIDlets. They are
inherently hard to debug because the
same error message can apply to a
number of problems.
The following is a list of possible solutions to prevent or correct verification errors:
If you started by building a Java
Archive (JAR) file and then used the
RIM Application Program Compiler
(RAPC) to create .cod files, make
sure you turn obfuscation off when
building the JAR file. The RAPC
compiler performs its own
obfuscation and issues may occur if
the code is already obfuscated.
Remove any System.out.* calls. These
generally do nothing on the
BlackBerry smartphone, but they
might cause verification errors.
Remove unused import statements.
Explicitly specify the access for
each function or variable. For
example, make sure each one is
specified as public, private, or
protected.
If you are working with a MIDlet,
make sure the MIDlet class is
declared as public.
Verification errors may occur if the
COD file is corrupted or if it was
not signed correctly. Make sure that
you perform a clean rebuild and that
you re-sign your application.
Reinstall the application on the
BlackBerry smartphone.
Comment out any non-executable code.
Verification errors might be related
to the size of the main code file
and the library files. If you
comment out non-executable code, the
file sizes change, which may correct
the problem.
If you have created any classes that
inherit from RIM classes, change the
name of any custom methods and
members that you created in those
classes. This makes sure that you
have not named any methods or
members of the same name in the
internal RIM classes.
If your application is using
BlackBerry® Device Software 3.8 or
later, verification errors occur
when an application that implements
the
javax.microedition.rms.RecordStore
class is compiled using BlackBerry®
Java® Development Environment
(BlackBerry JDE) earlier than
version 4.0. This occurs if the
application uses either the
addRecordListener or
removeRecordListener methods of the
RecordStore class. To resolve this
issue, recompile the application
using BlackBerry JDE 4.0 or later.
There is a problem with how the
BlackBerry® Java® Virtual Machine
(BlackBerry JVM) handles the
referencing of a class directly
within the constructor of another
class. The following is an example:
Class1 class1= new
Class1(Class2.class.getName());
To work around this issue, do not make the class call within a constructor as shown in the following example:
Class1 class1;
String className = Class2.class.getName();
Class1 = new Class1(className);
Remove references to a static instance variable from an inner class. For example, the following code example could cause an error:
public class MyOuterClass {
static int var;
class MyInnerClass {
public void doSomething() {
var = 7;
}
}
}
There are a few ways you can remove these references, such as creating get/set methods for var in the outer class or modifying the logic to pull MyInnerClass out of MyOuterClass.
The build procedure normally
compiles from the java source file
with the javac command, and then
runs preverify.exe file and then
RAPC. Add the following command line
arguments to javac to help avoid
issues in earlier versions of the
RAPC:
javac.exe -source 1.3 -target 1.1
Some methods that are very long can
cause verification errors. By
breaking these methods into helper
methods, you can reduce the
likelihood of verification errors.
Although not as likely, some very
long method definitions (with 10 or
more parameters), and some very long
constant definitions (long package
structure and/or long names) can
also cause verification errors.