保存app内容到手机桌面

本文详细介绍了如何在淘宝APP中实现桌面插件功能,包括安装描述文件、使用Safari生成webclip的方法及实现步骤,以及如何通过第三方库CocoaHTTPServer在APP端运行服务器以解决应用与Safari共享文件的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://www.cocoachina.com/ios/20150309/11270.html

今天,我发现淘宝手机app可以把用户喜欢的店铺保存到app的桌面上,感觉很神奇,研究了下怎么做,并记录下来顺便分享下心得。附上demo地址

下面是实际效果:
安装描述文件

profile.gif

safari生成webclip

safari1.gif

这种效果就是苹果的webclip,app上要生成它主要有2种方式。

通过安装描述文件的方式生成webclip

  • 使用iphone configuration utility生成一个webclip描述文件。

下载iphone configuration utility后配置一个描述文件,导出即可。

  • 使用safari安装这个描述文件。

使用[UIApplication sharedApplication] openURL:的方式无法直接打开描述文件,UIWebView也不支持打开这种文件类型。

safari是可以直接安装描述文件的,但是safari和应用是2个独立的沙盒,所以这里需要解决应用和safari共享文件的问题。这里使用的思路是把app作为一个服务器,让safari访问这个服务器获取到描述文件进行安装,因为程序进入后台后还可以运行一段时间,所以这里是可行的。

可以使用第三方库CocoaHTTPServer在app端运行一个服务器。safari中访问 loacalhost:端口号/目录即可打开文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
- (void)startServer
{
     // Create server using our custom MyHTTPServer class
     _httpServer = [[RoutingHTTPServer alloc] init];
     // Tell the server to broadcast its presence via Bonjour.
     // This allows browsers such as Safari to automatically discover our service.
     [_httpServer setType:@ "_http._tcp." ];
     // Normally there's no need to run our server on any specific port.
     // Technologies like Bonjour allow clients to dynamically discover the server's port at runtime.
     // However, for easy testing you may want force a certain port so you can just hit the refresh button.
     [_httpServer setPort:12345];
     NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
     [_httpServer setDocumentRoot:documentsDirectory];
     if  (_httpServer.isRunning) [_httpServer stop];
     NSError *error;
     if ([_httpServer start:&error])
     {
         NSLog(@ "Started HTTP Server on port %hu" , [_httpServer listeningPort]);
     }
     else
     {
         NSLog(@ "Error starting HTTP Server: %@" , error);
         // Probably should add an escape - but in practice never loops more than twice (bug filed on GitHub https://github.com/robbiehanson/CocoaHTTPServer/issues/88)
         [self startServer];
     }
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
     // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
     // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
     backgroundTask = [application beginBackgroundTaskWithExpirationHandler:^{
         [application endBackgroundTask:backgroundTask];
         backgroundTask = UIBackgroundTaskInvalid;
     }];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
     // Override point for customization after application launch.
     [self startServer];
     return  YES;
}

safari中打开关键代码

1
2
3
4
5
__weak AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
     UInt16 port = appDelegate.httpServer.port;
     NSLog(@ "%u" , port);
     if  (success) [[UIApplication sharedApplication] openURL:[NSURL URLWithString:[NSString stringWithFormat:@ "http://localhost:%u/profile.mobileconfig" , port]]];
     else  NSLog(@ "Error generating profile" );

通过safari自带功能生成webclip

safari带有一个为当前网页生成webclip的功能,现在我们就需要使用这个方式来生成webclip。

这种方式的工作流程是这样的:先使用app打开safari并显示指定的网页内容(一般是指导用户怎么使用safari生成webclip,并打开safari的js控制),然后用户打开js权限,保存webclip,下次用户点击桌面上的webclip后即可再次打开该网页,触发js,跳回app。

因为用户点开webclip的时候需要获取到网页的所有信息,又因为我们的应用不是长时间在后台运行的,所以需要把所有网页的内容以url的形式中保存在webclip中,这种技术叫做data-url技术。

我们需要app把网页内容通过data-url的形式传给safari,我尝试过使用openurl的传输方式,这种方式不能传输太长的数据,行不通。所以这里的思路也是把app变成一个服务器,safari访问的时候返回302让TA重定向,重定向的url返回我们要传输的data-url,safari重定向后即可显示我们指定的网页内容。这里我们可以用基于CocoaHTTPServer之上封装的库RoutingHTTPServer。

  • 配置并传输data-url

1
2
3
4
5
6
7
8
9
     //配置返回值
     [appDelegate.httpServer get:@ "/old"  withBlock:^(RouteRequest *request, RouteResponse *response) {
         [response setStatusCode:302];  // or 301
         [response setHeader:@ "Location"  value:@ "data:text/html;charset=UTF-8," ];
     }];
//跳转
     UInt16 port = appDelegate.httpServer.port;
     NSLog(@ "%u" , port);
     [[UIApplication sharedApplication] openURL:[NSURL URLWithString:[NSString stringWithFormat:@ "http://localhost:%u/old" , port]]];

用户打开js

58.png

通过safari保存webclip

59.png

  • data-url中加入js

通过safari打开的html是处于safari mode,而直接通过webclip打开的html是处于app mode,可以理解为safari mode是嵌入在safari中的网页,app mode的网页是单独的网页,通过这个状态我们可以控制什么时候调用js,来控制最终是展示当前网页还是跳转到我们指定的app。这里我写的是 sample:// ,可以按照需要替换成app的scheme,即可跳转到app。

1
<br>

其他可以做的细节

  • html和配置文件,我们都可以通过替换字符串等方式修改最终生成的内容,以此来针对不同用户生成不同内容。

1
2
3
4
5
6
7
NSString *templatePath = [[NSBundle mainBundle] pathForResource:@ "phone_template"  ofType:@ "mobileconfig" ];
     NSString *data = [NSString stringWithContentsOfFile:templatePath encoding:NSUTF8StringEncoding error:NULL];
     data = [data stringByReplacingOccurrencesOfString:@ "!!NAME!!"  withString:name];
     data = [data stringByReplacingOccurrencesOfString:@ "!!PHONENUMBER!!"  withString:phoneNumber];
     NSLog(@ "%@" , data);
     BOOL success = [data writeToFile:[ProfileGenerator profilePath] atomically:YES encoding:NSUTF8StringEncoding error:nil];
     return  success;
  • 端口号不一定要写死,这里仅仅是方便测试。

总结

2种方式都可以达到最终效果,选取哪种方式去实现,可以自己评估优劣。由于本人对服务端和前端不太熟悉,实现还有2点不足之处,希望有人能给出些比较好的方案。

可能由于浏览器缓存的问题,如果之前safari打开过localhost:端口号,下次再进入时可能不会去重定向,导致webclip保存的不是重定向后的url,而是原本请求的url。

重定向返回的response header长度这里也是有限制的,过长会造成截断,这里应该是可以通过代码改进的。


<think>好的,我现在需要回答用户关于如何使用PyCharm进行手机App开发的询问。首先,用户提供的引用中有提到PyCharm支持Django和Google App Engine,还提到了使用Kivy和BeeWare这两个Python库来开发手机App。不过用户特别问到的是PyCharm本身如何进行手机App开发,所以可能需要结合这些第三方库来回答。 首先,我需要确认PyCharm是否直接支持手机App开发。根据引用[1],PyCharm支持Django和Google App Engine,但没有直接提到Android或iOS开发。引用[2]、[3]、[4]、[5]提到了使用Kivy和BeeWare这两个库,以及可能需要虚拟机或特定工具链。这说明虽然PyCharm本身是Python IDE,但通过集成第三方库和工具,可以实现手机App开发。 接下来,我需要整理步骤。用户需要教程或方法,所以应该分步骤说明如何在PyCharm中配置环境,安装Kivy或BeeWare,创建项目,编写代码,以及打包成手机应用。同时,引用中提到Kivy需要Linux环境或虚拟机,而BeeWare可能也有类似需求,需要注意这点。 另外,用户可能对具体操作有疑问,比如如何配置虚拟环境,如何调试,如何打包。需要详细说明这些步骤,并结合引用中的信息,比如引用[4]提到buildozer只能在Linux使用,所以需要提醒用户可能需要虚拟机。同时,引用[5]提到了具体的文件操作步骤,可能需要指导用户如何在PyCharm中管理项目文件并转移到虚拟机中进行打包。 最后,生成相关问题,可能涉及性能优化、调试技巧、其他框架比较等,需要根据引用内容合理设计。</think>### 使用PyCharm开发手机App的方法 PyCharm虽未直接提供手机App开发模板,但可通过集成第三方库(如Kivy、BeeWare)实现跨平台移动应用开发。以下是具体步骤: #### 1. **选择开发框架** - **Kivy**:适合开发跨平台(Android/iOS)应用,支持触控交互设计[^4]。 - **BeeWare(Toga)**:提供原生界面组件,需配合工具链打包为平台应用[^3]。 #### 2. **PyCharm环境配置** - **安装库**:在PyCharm中通过`File > Settings > Python Interpreter`安装`kivy`或`toga`: ```bash pip install kivy # Kivy安装 pip install toga # BeeWare的GUI库 ``` - **创建项目**:新建Python项目,选择虚拟环境以隔离依赖[^1]。 #### 3. **编写应用代码** - **Kivy示例**(保存为`main.py`): ```python from kivy.app import App from kivy.uix.button import Button class MyApp(App): def build(self): return Button(text='Hello Kivy') if __name__ == '__main__': MyApp().run() ``` - **BeeWare示例**(使用Toga): ```python import toga def button_handler(widget): print("Hello BeeWare") def build(app): box = toga.Box() button = toga.Button('Click me', on_press=button_handler) box.add(button) return box if __name__ == '__main__': app = toga.App('First App', 'org.example', startup=build) app.main_loop() ``` #### 4. **调试与运行** - 在PyCharm中直接运行`main.py`,预览桌面端效果(Kivy/BeeWare均支持桌面调试)。 - 使用PyCharm的调试工具(断点、变量监视)优化逻辑。 #### 5. **打包为手机应用** - **Kivy**: 1. 在Linux系统中安装`buildozer`(需虚拟机如Ubuntu)。 2. 通过命令行生成Android APK: ```bash buildozer init # 生成配置文件 buildozer android debug # 编译APK ``` - **BeeWare**: 1. 安装打包工具`briefcase`: ```bash pip install briefcase ``` 2. 生成Android项目并编译: ```bash briefcase create android # 创建模板 briefcase build android # 构建APK briefcase run android # 模拟器运行 ``` #### 6. **注意事项** - Kivy的界面需手动适配移动端触控逻辑,而BeeWare支持原生组件渲染。 - 若使用Windows,需通过虚拟机完成Kivy的APK打包[^4][^5]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值