symbian 2nd如何绕过程序管理器的限制

symbian 2nd如何绕过程序管理器的限制

 

北京理工大学  20981  陈罡

 

symbian开发中我们经常会用到手机系统自带的程序管理这个软件。 这个软件的功能在于它会忠实地把程序的安装操作记录下来,在删除 程序的时候它也会忠实地把程序给删除。这种做法对于symbian来说, 无疑是最好的选用第三方软件的选择,既可以安装到手机上,又可以 无条件的将软件卸载掉。

 

但是这个所谓的程序管理,也有很多弊端。例如,每次都需要把程序 的安装包拷贝到手机存储上去,这样安装包一旦大于 2M ,对于多数s60 手机来说,这个程序极有可能引起手机内存不足,请关闭一些程序这样 的错误提示,最终导致安装失败。再有就是程序的升级,有的时候不需要 整个将sis包重新安装一遍,只是覆盖掉几个dll文件即可,但是很多情况 下,开发者都是选择将程序全部重新安装一遍,如果打包的时候升级过sis 包的版本,那么将在程序管理中看到多个安装记录。另外目前很多公司 都在寻找手机程序预装的方法,其实从其本质来说就是希望程序安装到 用户的手机上以后,无法被用户使用普通的程序管理程序卸载。

 

在这里我要讨论一种方式,可以绕过程序管理器的限制,在程序管理 里面没有记录,也无法把程序从程序管理器里面卸载,这种方式虽然比较 有效,但是程序的卸载操作就需要使用其它的单独的卸载程序才能卸载了。

绕过程序管理器的方法其实很简单,自己编写一个程序管理器即可。很多 朋友会想编写一个程序管理器多么多么的复杂,需要熟悉sis文件格式之类 的内容。其实一点也不复杂,sis本身就是s60自带的程序管理器支持的文件 格式,只有nokia的程序管理器才能够识别。既然我们自己编写程序管理器 的话,就不必拘泥于sis格式了。自己的程序可以读取的文件格式就可以自己 说得算了。

 

我们知道在创建pkg文件的时候,在需要安装后立即运行的程序后面通常只要 指定一个RI,FI,就可以保证程序在安装后可以立即执行,例如: "marm/myapp.exe"-"!:/System/Apps/MyApp/Myapp.exe",RI,FI

这样就提供了一个方法摆脱当前的程序管理器的方法,大致的思路如下: 编写一个exe文件,该文件可以将某个.zip或者.dat的包解压缩到手机的 e:/system/apps目录下面即可。

 

整体的写下来,大概是这个样子的: "marm/my.zip"-"!:/System/Apps/MyApp/my.zip" "marm/myapp.exe"-"!:/System/Apps/MyApp/myapp.exe",RI,FI myapp.exe运行的时候,可以给它加入适当的1秒至3秒的延时,用来确保 手机的程序管理器已经把zip包释放到某个目录下面去了,然后再开始运行 myapp.exe,它的作用在于直接把my.zip包中的文件解压缩到system/apps目录 或者希望可以开机自动运行的可以把相关的mdl文件考入c:/system/recogs目录。

注意: 利用mdl在手机启动的时候自动载入的特性实现的所谓开机自动运行,在 symbian 3rd平台中已经不再适用,以下是官方的issues说明:

这样一来,只有my.zipmyapp.exe这两个文件是纳入手机的应用程序管理器 的控制范畴的,可以很容易地通过应用程序管理器删除,但是通过myapp.exe my.zip中解压缩出来的,放入system/apps里面的目录则成功的逃脱了程序 管理器的限制,保留了下来。这样就基本上实现了,程序脱离应用程序管理器 的限制了。如果在my.zip中加入自动运行的mdl,然后调用自动登陆、下载zip 自动解压缩的程序的话,就可以实现程序的自动更新了。每次让开机自动运行 的程序,在收到更新短信时启动,联网,下载更新包,然后解压缩安装。这 一切都是以后台的方式运行的,不会对用户产生困扰,也不需要用户每次都通过 nokia pc套件来下载,安装程序的繁琐过程。

 

对用户来说,只是某天突然发现不知道什么时候手机中多了一个应用程序的 图标 :),或者发现某个程序的图标不见了(可以通过网络自动删除手机中的某个 无效的应用)。相当于自己实现了一个OTA了。

 

相关实验我已经完全测试成功,呵呵。但是这种OTA是一把双刃剑 不希望落入某些居心不良的人的手中,扰乱这个技术的发展。所以就暂时不开放 代码了,只是把解压缩my.zipmyapp.exe代码开放一下,希望对有兴趣的朋友 有用:

// -------------------------------------------------------------------------- // zagzip.cpp // // programmer : wayne // (1)get zip file exactly pathname // (2)set path where package need to be extracted // (3)check whether the object directory exists // (4)if directory exists, perform extract operaion // (5)if not exists, create one, then, goto step (4) // (6)call outer command, delete zip file and quit smoothly // --------------------------------------------------------------------------

#include <e32base.h> #include <e32std.h> #include <f32file.h>  // RFs and RFile #include <zipfile.h>  // CZipFile #include <apacmdln.h> // CApaCommandLine #include <EikDll.h>   // EDll::StartApp(...) #include <apgcli.h> #include <apgtask.h> #include <s32file.h>    // RFileReadStream, RFileWriteStream

 

// use 4k buffer size #define BUF_SIZE  1024 * 4

 

// the specified zip config file name #ifndef __WINS__ _LIT(KZipPathnameC,  "c://my.zip") ; _LIT(KZipPathnameE,  "e://my.zip") ; _LIT(KExtractPath,   "c://system//apps//abc//") ; _LIT(KSrcPathname,   "c://system//apps//abc//abc.mdl") ; _LIT(KObjPathname,   "c://system//recogs//abc.mdl") ; _LIT(KOutCmd,   "c://system//apps//abc//abc.app") ; #else _LIT(KZipPathnameC,  "c://my.zip") ; _LIT(KZipPathnameE,  "c://my.zip") ; _LIT(KExtractPath,   "c://system//apps//abc//") ; _LIT(KSrcPathname,   "c://system//apps//abc//abc.mdl") ; _LIT(KObjPathname,   "c://recogs//abc.mdl") ; _LIT(KOutCmd,    "c://system//apps//abc//abc.app") ; #endif

 

TBuf8<BUF_SIZE>  g_buf ; TBuf<100>   g_zip_pathname ; TBuf<100>   g_target_path ; TBuf<100>   g_copy_src_pathname ; TBuf<100>   g_copy_obj_pathname ; TBuf<100>   g_run_command ;

 

// Constants LOCAL_C TBool check_file_exist(const TDesC & path_name) ; LOCAL_C TBool check_dir_exist(const TDesC & dir_name) ; LOCAL_C TBool extract_zipfile(const TDesC & zip_pathname, const TDesC & target_path) ; LOCAL_C TBool extract_single(RFs& fs,         CZipFile * zip_file,         const TDesC& target_path,         const TDesC& file_name) ; LOCAL_C TBool run_command(TDesC& preset_command) ; LOCAL_C TBool copy_file(TDesC& obj_pathname, TDesC& src_pathname) ; LOCAL_C TBool get_const_string(TDes & res_str,const TDesC & const_str) ; LOCAL_C TBool main_proc() ;

 

//检查文件是否存在 LOCAL_C TBool check_file_exist(const TDesC & path_name) {  RFs fs ;  RFile f ;  TInt res ;  User::LeaveIfError(fs.Connect()) ;  res = f.Open(fs, path_name, EFileRead) ;  f.Close() ;  fs.Close() ;  return (res == KErrNone) ? ETrue : EFalse ;  }

 

// 检查目录是否存在 LOCAL_C TBool check_dir_exist(const TDesC & dir_name) {  RFs  fs ;  RDir dir ;  TInt res ;  User::LeaveIfError(fs.Connect()) ;  res = dir.Open(fs, dir_name, KEntryAttNormal) ;  dir.Close() ;  fs.Close() ;  return (res == KErrNone) ? ETrue : EFalse ; }

 

// 解压缩zip包了 LOCAL_C TBool extract_zipfile(const TDesC& zip_pathname, const TDesC& target_path) {  // Connect to the file server.  RFs fs ;  User::LeaveIfError(fs.Connect()) ;

 // Create an instance of CZipFile.  CZipFile* zip_file = CZipFile::NewL(fs, zip_pathname) ;  CleanupStack::PushL(zip_file) ;    // Iterate all the files inside the .zip file and then decompress it  CZipFileMemberIterator* members = zip_file->GetMembersL();  CZipFileMember* member = NULL ;  CleanupStack::PushL(members);

 // 这里是确保解压缩的目的目录存在,如果不存在就创建一个  if(!check_dir_exist(target_path)) {   // target path doesn't exist, create one   fs.MkDir(target_path) ;  }

 // iterator one by one  while ((member = members->NextL()) != 0) {   // extract the compressed file into the specified directory   if(check_file_exist(*member->Name())) {    TParse parse ;    parse.Set(*member->Name(), NULL, NULL) ;    // 如果有被占用的rsc,则跳过,继续运行    // 这一点主要针对程序正在运行中的情况,rsc不可写    if(parse.Ext().Find(_L("rsc")) != KErrNotFound) continue ;   }   extract_single(fs, zip_file, target_path, *member->Name()) ;   delete member;  }  CleanupStack::PopAndDestroy(); // members  CleanupStack::PopAndDestroy(); // zip_file  fs.Close();  return 0 ; }

 

// 解压缩一个文件 LOCAL_C TBool extract_single(RFs& fs,         CZipFile * zip_file,         const TDesC& target_path,         const TDesC& file_name) {   TInt total_size = 0 ;  TUint uncompressed_size = 0 ;    // Get the input stream of aFileName.  CZipFileMember* member = zip_file->CaseInsensitiveMemberL(file_name);  CleanupStack::PushL(member);  RZipFileMemberReaderStream* stream;  zip_file->GetInputStreamL(member, stream);  CleanupStack::PushL(stream);

 // Extracts file_name to a buffer.  TFileName target_pathname ;  RFile file ;  target_pathname.Append(target_path) ;  target_pathname.Append(file_name) ;  User::LeaveIfError(file.Replace(fs, target_pathname, EFileWrite));  CleanupClosePushL(file);    total_size = member->UncompressedSize() ;  while(total_size > 0) {   // if the file is quite huge, then read the file in streaming mode.   // use 4KB buffer and save binary raw data into uncompressed file   // 这里使用了4K的缓冲区去分段解压缩大的zip文件   g_buf.SetLength(0) ;      if(total_size >= BUF_SIZE) uncompressed_size = BUF_SIZE ;   else uncompressed_size = total_size ;   User::LeaveIfError(stream->Read(g_buf, uncompressed_size)) ;   User::LeaveIfError(file.Write(g_buf)) ;   total_size -= uncompressed_size ;  }  // Release all the resources.  file.Flush() ;  CleanupStack::PopAndDestroy(3); // file, stream, member  return 0 ; }

 

// 这是执行外部命令了 LOCAL_C TBool run_command(TDesC& preset_command) {  if(check_file_exist(preset_command)) {   CApaCommandLine * command_line = CApaCommandLine::NewLC();   command_line->SetLibraryNameL(preset_command) ;   command_line->SetCommandL(EApaCommandRun);   User::LeaveIfError(EikDll::StartAppL(*command_line));   CleanupStack::PopAndDestroy(command_line) ;   return ETrue ;  }  return EFalse ; }

 

// 复制文件,貌似应该有更好的方法,这里自己写了一个了 // 应对recogs目录不存在的情况 LOCAL_C TBool copy_file(TDesC& obj_pathname, TDesC& src_pathname) {  RFs     fs ;  RFile    fsrc ;  RFile    fobj ;  TInt    total_bytes ;  TInt    used_bytes ;  TParse    pathname_parse ;  TBuf<50>   copy_dir ;  

 User::LeaveIfError(fs.Connect()) ;

 // check whether the object dir is exist  pathname_parse.Set(obj_pathname, NULL, NULL) ;  copy_dir = pathname_parse.DriveAndPath() ;  if(!check_dir_exist(copy_dir)) {   fs.MkDir(copy_dir) ;    }    fsrc.Open(fs, src_pathname, EFileStream | EFileRead) ;  fobj.Replace(fs, obj_pathname, EFileStream | EFileWrite) ;    fsrc.Size(total_bytes) ;    while(total_bytes > 0) {   if(total_bytes >= BUF_SIZE) used_bytes = BUF_SIZE ;   else used_bytes = total_bytes ;   fsrc.Read(g_buf) ;   fobj.Write(g_buf) ;   total_bytes -= used_bytes ;    }  fs.Close() ;  return ETrue; }

 

LOCAL_C TBool get_const_string(TDes & res_str,const TDesC & const_str) {  res_str.SetLength(0) ;  if(check_file_exist(const_str)) {   res_str.Copy(const_str) ;   return ETrue ;  }  return EFalse ; }

LOCAL_C TBool main_proc() {  TBool    has_running_app = EFalse ;  RFs     fs ;  RFile    f ;  TBuf8<10>   s ;

 // 检查文件  if(check_file_exist(KOuterCmd)) has_running_app = ETrue ;

 User::LeaveIfError(fs.Connect()) ;  f.Replace(fs, KQuitFile, EFileWrite) ;  s.Format(_L8("quit")) ;  f.Write(s) ;  f.Flush() ;  f.Close() ;  fs.Close() ;

 // 确定zip文件存在在C盘还是E,把路径存入g_zip_pathname  if(!get_const_string(g_zip_pathname, KZipPathnameE)) {   get_const_string(g_zip_pathname, KZipPathnameC) ;  }

 // 解压缩后文件的目标存放路径  g_target_path.Copy(KExtractPath) ;     // 解压缩后mdl文件的存放路径  g_copy_src_pathname.Copy(KSrcPathname) ;

 // 解压缩后将mdl文件拷贝到的目标路径  g_copy_obj_pathname.Copy(KObjPathname) ;

 // 这是都执行完毕后需要运行的外部命令,类似FI,RI的功能     g_run_command.Copy(KOuterCmd) ;    // 这就是解压的过程了  extract_zipfile(g_zip_pathname, g_target_path) ;

 // 这里主要是为了把mdl文件拷贝到c://system//recogs这个目录下而加入的  copy_file(g_copy_obj_pathname, g_copy_src_pathname) ;

 // 最后运行常驻内存的那个exeapp  if(!has_running_app) run_command(g_run_command) ;

 // 删除zip文件和mdl文件  User::LeaveIfError(fs.Connect()) ;  fs.Delete(g_zip_pathname) ;  fs.Delete(g_copy_src_pathname) ;  fs.Close() ;  return 0 ; }

 

//  从这里跑到自己定义的那个函数里面去 LOCAL_C void MainL(const TDesC& /*aArgs*/)  {   main_proc() ;  }

 

LOCAL_C void DoStartL()  {  // 没法子,在exe中要使用活动对象,只能自己创建调度器  CActiveScheduler* scheduler = new (ELeave) CActiveScheduler();  CleanupStack::PushL(scheduler);  CActiveScheduler::Install(scheduler);

 // 调用MainL函数,开始解压缩  TBuf<256> cmdLine;  RProcess().CommandLine(cmdLine);  MainL(cmdLine);

 // 删除调度器  CleanupStack::PopAndDestroy(scheduler);  }

// 这个是整个程序的入口点了 GLDEF_C TInt E32Main()  {  // 连异常处理栈都要自己创建  __UHEAP_MARK;  CTrapCleanup* cleanup = CTrapCleanup::New();  // Run application code inside TRAP harness, wait keypress when terminated  TRAPD(mainError, DoStartL());    delete cleanup;  __UHEAP_MARKEND;  return KErrNone;  }

// End of File

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值